diff --git a/.gitignore b/.gitignore
index e43b0f9..af56f61 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
.DS_Store
+.idea/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..cf0c89c
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "external/mLib"]
+ path = external/mLib
+ url = https://github.com/niessner/mLib
diff --git a/Alignment/README.md b/Alignment/README.md
new file mode 100644
index 0000000..01c3245
--- /dev/null
+++ b/Alignment/README.md
@@ -0,0 +1,15 @@
+## Aligner for scanned .sens, .ply files
+=========================================
+
+Transforms scans to z-up alignment for scans and tries to align walls to x-y planes.
+
+### Installation.
+This code was developed under VS2013.
+
+Requirements:
+- our research library mLib, a git submodule in ../external/mLib
+- mLib external libraries can be downloaded [here](https://www.dropbox.com/s/fve3uen5mzonidx/mLibExternal.zip?dl=0)
+
+
+To run:
+`alignment.exe [path to directory of scan to align]`
\ No newline at end of file
diff --git a/Alignment/alignment.sln b/Alignment/alignment.sln
new file mode 100644
index 0000000..ef6367d
--- /dev/null
+++ b/Alignment/alignment.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "alignment", "alignment.vcxproj", "{EB0D04B5-579C-4BF9-8FC3-58DFB235231F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {EB0D04B5-579C-4BF9-8FC3-58DFB235231F}.Debug|x64.ActiveCfg = Debug|x64
+ {EB0D04B5-579C-4BF9-8FC3-58DFB235231F}.Debug|x64.Build.0 = Debug|x64
+ {EB0D04B5-579C-4BF9-8FC3-58DFB235231F}.Release|x64.ActiveCfg = Release|x64
+ {EB0D04B5-579C-4BF9-8FC3-58DFB235231F}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Alignment/alignment.vcxproj b/Alignment/alignment.vcxproj
new file mode 100644
index 0000000..02c79cc
--- /dev/null
+++ b/Alignment/alignment.vcxproj
@@ -0,0 +1,105 @@
+
+
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+
+
+ Create
+ Create
+
+
+
+ {EB0D04B5-579C-4BF9-8FC3-58DFB235231F}
+ alignment
+
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ false
+ v120
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+ ../external/mLib/include;../external/mLibExternal/include/;./src/;$(IncludePath)
+ ..\external\mLibExternal\libsWindows\lib64;$(LibraryPath)
+
+
+ ../external/mLib/include;../external/mLibExternal/include/;./src/;$(IncludePath)
+ ..\external\mLibExternal\libsWindows\lib64;$(LibraryPath)
+
+
+
+ Level3
+ Disabled
+ true
+ _CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions)
+ Use
+ -Zm400 %(AdditionalOptions)
+
+
+ true
+ freeimage.lib;%(AdditionalDependencies)
+
+
+
+
+ Level2
+ MaxSpeed
+ true
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+ Use
+ -Zm400 %(AdditionalOptions)
+
+
+ true
+ true
+ true
+ freeimage.lib;%(AdditionalDependencies)
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Alignment/alignment.vcxproj.filters b/Alignment/alignment.vcxproj.filters
new file mode 100644
index 0000000..2c9c538
--- /dev/null
+++ b/Alignment/alignment.vcxproj.filters
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Alignment/src/alignment.h b/Alignment/src/alignment.h
new file mode 100644
index 0000000..588c020
--- /dev/null
+++ b/Alignment/src/alignment.h
@@ -0,0 +1,366 @@
+
+#pragma once
+
+#include "stdafx.h"
+
+#include "processedFile.h"
+#include "planeExtract.h"
+
+class Alignment {
+public:
+
+ static MeshDataf makeNormalMesh(const vec3f& p0, const vec3f& p1, const vec4f& color = vec4f(0.8f, 0.2f, 0.2f, 1.0f))
+ {
+ TriMeshf normalMesh0 = Shapesf::sphere(0.05f, p0, 10, 10, color);
+ TriMeshf normalMesh1 = Shapesf::cylinder(p0, p1, 0.025f, 10, 10, color);
+ MeshDataf nMesh = normalMesh0.computeMeshData();
+ nMesh.merge(normalMesh1.computeMeshData());
+ return nMesh;
+ }
+
+
+
+ static vec3f upVectorFromViews(const SensorData& sd) {
+ vec3f v(0.0f, 0.0f, 0.0f);
+ for (size_t i = 0; i < sd.m_frames.size(); i++) {
+ const mat4f& t = sd.m_frames[i].getCameraToWorld();
+ if (sd.m_frames[i].getCameraToWorld()(0, 0) == -std::numeric_limits::infinity()) continue;
+
+ const vec3f cameraUp(0.0f, -1.0f, 0.0f);
+ const vec3f worldUp = (t.getRotation() * cameraUp).getNormalized();
+ v += worldUp;
+ }
+ v /= (float)sd.m_frames.size();
+ return v.getNormalized();
+ }
+
+ static bool hasAccel(const SensorData& sd, unsigned int numThresh = 10) {
+ unsigned int numValidAccel = 0;
+ for (const SensorData::IMUFrame& f : sd.m_IMUFrames) {
+ if (f.acceleration != vec3d(0.0)) numValidAccel++;
+ }
+
+ if (numValidAccel > numThresh) return true;
+ else return false;
+ }
+
+ static vec3f upVectorFromAccel(const SensorData& sd)
+ {
+ if (sd.m_IMUFrames.size() == 0) throw MLIB_EXCEPTION("no imu data found");
+
+ vec3f v(0.0f, 0.0f, 0.0f);
+ for (size_t i = 0; i < sd.m_frames.size(); i++) {
+ const SensorData::IMUFrame& f = sd.findClosestIMUFrame(i);
+
+ if (sd.m_frames[i].getCameraToWorld()(0, 0) == -std::numeric_limits::infinity()) continue;
+
+ if (f.acceleration == vec3d::origin) {
+ std::cout << "invalid IMU acceleration data entry at " << i << "-th frame" << std::endl;
+ continue;
+ }
+
+ vec3f cameraUp = -vec3f((float)f.acceleration.x, (float)f.acceleration.y, (float)f.acceleration.z).getNormalized();
+ const mat4f& t = sd.m_frames[i].getCameraToWorld();
+ const vec3f worldUp = (t.getRotation() * cameraUp).getNormalized();
+ v += worldUp;
+ }
+
+ return v.getNormalized();
+ }
+
+ static bool hasGravity(const SensorData& sd, unsigned int numThresh = 10)
+ {
+ unsigned int numValidGravity = 0;
+ for (const SensorData::IMUFrame& f : sd.m_IMUFrames) {
+ if (f.gravity != vec3d(0.0)) numValidGravity++;
+ }
+
+ if (numValidGravity > numThresh) return true;
+ else return false;
+ }
+
+ static vec3f upVectorFromGravity(const SensorData& sd)
+ {
+ if (sd.m_IMUFrames.size() == 0) throw MLIB_EXCEPTION("no imu data found");
+
+ vec3f v(0.0f, 0.0f, 0.0f);
+ for (size_t i = 0; i < sd.m_frames.size(); i++) {
+ const SensorData::IMUFrame& f = sd.findClosestIMUFrame(i);
+ if (sd.m_frames[i].getCameraToWorld()(0, 0) == -std::numeric_limits::infinity()) continue;
+
+ if (f.gravity == vec3d::origin) {
+ std::cout << "invalid IMU gravity data entry at " << i << "-th frame" << std::endl;
+ continue;
+ }
+
+ vec3f cameraUp = vec3f((float)f.gravity.x, (float)f.gravity.y, (float)f.gravity.z).getNormalized();
+
+ cameraUp = vec3f(cameraUp.y, cameraUp.x, cameraUp.z);
+
+ const mat4f& t = sd.m_frames[i].getCameraToWorld();
+ const vec3f worldUp = (t.getRotation() * cameraUp).getNormalized();
+ v += worldUp;
+ }
+ v /= (float)sd.m_frames.size();
+
+ return v.getNormalized();
+ }
+
+ static void writeTrajectoryFile(const std::string& outFile, const SensorData& sd) {
+
+ std::vector trajecotry;
+ for (size_t i = 0; i < sd.m_frames.size(); i++) {
+ trajecotry.push_back(sd.m_frames[i].getCameraToWorld());
+ }
+
+ BinaryDataStreamFile outStream(outFile, true);
+ outStream << trajecotry;
+ outStream.close();
+ }
+
+ static std::vector readTrajectoryFile(const std::string& inFile) {
+ BinaryDataStreamFile in(inFile, false);
+ std::vector trajectory;
+ in >> trajectory;
+ return trajectory;
+ }
+
+ static void removeInvalidIMUFrames(SensorData& sd) {
+ const bool checkTimeStamp = true; //at the moment only remove invalid time frames
+ const bool checkGravity = false;
+ const bool checkAccel = false;
+
+ unsigned int removedInvalidFrames = 0;
+ for (std::vector::iterator iter = sd.m_IMUFrames.begin(); iter != sd.m_IMUFrames.end();) {
+ bool rem = false;
+ if (checkTimeStamp && iter->timeStamp == 0) rem = true;
+ if (checkGravity && iter->gravity == vec3d::origin) rem = true;
+ if (checkAccel && iter->gravity == vec3d::origin) rem = true;
+
+ if (rem == true) {
+ iter = sd.m_IMUFrames.erase(iter);
+ removedInvalidFrames++;
+ }
+ else {
+ iter++;
+ }
+ }
+
+ if (removedInvalidFrames > 0) {
+ std::cout << "removed " << removedInvalidFrames << " invalid IMUFrames" << std::endl;
+ }
+ }
+
+ static void alignScan(const std::string& path, bool forceRealign = false) {
+
+ const std::string processedFile(path + "/" + "processed.txt");
+ if (!util::fileExists(processedFile)) {
+ std::cout << "no reconstruction available for " << path << "\n\t -> skipping folder" << std::endl;
+ return;
+ }
+ ParameterFile parameterFile(processedFile);
+ ProcessedFile pf; pf.readMembers(parameterFile);
+ if (!pf.valid) {
+ std::cout << "reconstruction was invalid for " << path << "\n\t -> skipping folder" << std::endl;
+ return;
+ }
+ if (pf.aligned && !forceRealign) {
+ std::cout << "reconstruction is already aligned " << path << "\n\t -> skipping folder" << std::endl;
+ return;
+ }
+
+ Directory dir(path);
+ const std::vector tmp = ml::util::split(util::replace(path, "\\", "/"), "/"); //we assume forward slashes
+ const std::string base = tmp.back();
+ const std::string baseFile = path + "/" + base;
+
+ const std::string sensFile = path + "/" + base + ".sens";
+ const std::string plyFile = path + "/" + base + ".ply";
+ const std::string trajFile = util::replace(sensFile, ".sens", ".traj");
+
+
+ mat4f transform = mat4f::identity();
+
+ SensorData sd(sensFile);
+ removeInvalidIMUFrames(sd);
+
+ if (sd.m_frames.size() == 0) throw MLIB_EXCEPTION("no frames found in the sensor file");
+
+ if (sd.m_frames[0].getCameraToWorld() != mat4f::identity()) {
+ std::cout << "already found a previous alignment -> reverting to original" << std::endl;
+
+ if (sd.m_frames[0].getCameraToWorld()(0, 0) == -std::numeric_limits::infinity()) {
+ std::cout << "error can't revert due to an invalid transform in the first frame" << std::endl;
+ std::cout << "\tskipping folder " << std::endl;
+ return;
+ }
+ mat4f inverse = sd.m_frames[0].getCameraToWorld().getInverse();
+ sd.applyTransform(inverse);
+
+ //if we have a multiple ply files (e.g., if VH was already run):
+ Directory dir(path);
+ std::vector plyFiles = dir.getFilesWithSuffix(".ply");
+ for (const std::string& plyFile : plyFiles) {
+ MeshDataf md = MeshIOf::loadFromFile(dir.getPath() + "/" + plyFile);
+ md.applyTransform(inverse);
+ MeshIOf::saveToFile(dir.getPath() + "/" + plyFile, md);
+ }
+ }
+
+ MeshDataf md = MeshIOf::loadFromFile(plyFile);
+ md.mergeCloseVertices(0.0005f, true);
+ md.removeIsolatedPieces(5000);
+
+ //compute approx up vector from camera views or gravity (if available)
+ if (true) {
+ vec3f upEstimateView = upVectorFromViews(sd);
+ vec3f upEstimate = upEstimateView;
+ if (hasGravity(sd)) { //try to use gravity if possible
+ vec3f upEstimateGrav = upVectorFromGravity(sd);
+ upEstimate = upEstimateGrav;
+ }
+
+ vec3f x = upEstimate ^ vec3f(upEstimate.y, -upEstimate.z, upEstimate.x); x.normalize();
+ vec3f y = upEstimate ^ x; y.normalize();
+ vec3f z = upEstimate;
+ mat4f mat = mat4f(x, y, z);
+ md.applyTransform(mat);
+ transform = mat * transform;
+ }
+
+ md.computeVertexNormals();
+
+ //attempting to find a ground plane (and align to it)
+ if (true) {
+ PlaneExtract pe(md);
+ pe.cluster();
+ pe.removeSmallClusters();
+ pe.removeNonBoundingClusters(0.1f, 100); //the
+ const auto& clusters = pe.getClusters();
+
+ bool foundHorizontalPlane = false;
+ const size_t maxClusters = clusters.size();
+ size_t i = 0;
+ for (const Cluster& c : clusters) {
+ if ((c.m_rep.plane.getNormal() | vec3f(0.0f, 0.0f, 1.0f)) > 0.8f) {
+ mat4f mat = c.reComputeNormalAlignment();
+ md.applyTransform(mat);
+ transform = mat * transform;
+ foundHorizontalPlane = true;
+ break;
+ }
+ i++;
+ if (i >= maxClusters) break;
+ }
+ if (!foundHorizontalPlane) std::cout << "could not find a horizontal plane" << std::endl;
+
+ //final alignment with xy plane (translation)
+ if (true) {
+ BoundingBox3f bb = md.computeBoundingBox();
+ mat4f mat = mat4f::translation(-bb.getMinZ());
+ transform = mat * transform;
+ md.applyTransform(mat);
+
+ bb = md.computeBoundingBox();
+ mat = mat4f::translation(-vec3f(bb.getCenter().x, bb.getCenter().y, 0.0f));
+ md.applyTransform(mat);
+ transform = mat * transform;
+ }
+
+ //attempting to find a vertical plane to align with the x and y axis
+ if (true) {
+ if (true) {
+ //first find the bounding box using cgal
+ OrientedBoundingBox3f obb = CGALWrapperf::computeOrientedBoundingBox(md.m_Vertices, CGALWrapperf::CONSTRAIN_Z);
+ mat4f mat = mat4f(obb.getAxisX().getNormalized(), obb.getAxisY().getNormalized(), obb.getAxisZ().getNormalized());
+ md.applyTransform(mat);
+ transform = mat * transform;
+ }
+
+ //make sure x and y are in the positive quadrant
+ if (true) {
+ BoundingBox3f bb = md.computeBoundingBox();
+ mat4f mat = mat4f::translation(-vec3f(bb.getMin().x, bb.getMin().y, 0.0f));
+ md.applyTransform(mat);
+ transform = mat * transform;
+ }
+ }
+ }
+
+ md.m_Normals.clear();
+
+ {
+ //if we have a multiple ply files (e.g., if VH was already run):
+ Directory dir(path);
+ std::vector plyFiles = dir.getFilesWithSuffix(".ply");
+ for (const std::string& plyFile : plyFiles) {
+ MeshDataf mesh = MeshIOf::loadFromFile(dir.getPath() + "/" + plyFile);
+ mesh.applyTransform(transform);
+ MeshIOf::saveToFile(dir.getPath() + "/" + plyFile, mesh);
+ }
+
+
+ sd.applyTransform(transform);
+ sd.saveToFile(sensFile);
+ pf.aligned = true; //it's now aligned
+ pf.saveToFile(processedFile);
+ }
+ }
+
+ static mat4f readTransformFromAln(const std::string& filename)
+ {
+ std::ifstream s(filename);
+ if (!s.is_open()) throw MLIB_EXCEPTION("failed to open file " + filename + " for read");
+ std::string tmp;
+ std::getline(s, tmp); std::getline(s, tmp); std::getline(s, tmp);//ignore header lines
+ mat4f m;
+ for (unsigned int i = 0; i < 16; i++) s >> m[i];
+ s.close();
+ return m;
+ }
+
+ static void alignScanFromAlnFile(const std::string& path) {
+
+ const std::string processedFile(path + "/" + "processed.txt");
+ if (!util::fileExists(processedFile)) {
+ std::cout << "no reconstruction available for " << path << "\n\t -> skipping folder" << std::endl;
+ return;
+ }
+ ParameterFile parameterFile(processedFile);
+ ProcessedFile pf; pf.readMembers(parameterFile);
+ if (!pf.valid) {
+ std::cout << "reconstruction was invalid for " << path << "\n\t -> skipping folder" << std::endl;
+ return;
+ }
+
+ Directory dir(path);
+ const std::vector tmp = ml::util::split(util::replace(path, "\\", "/"), "/"); //we assume forward slashes
+ const std::string base = tmp.back();
+ const std::string baseFile = path + "/" + base;
+
+ const std::string alnFile = path + "/alignment.aln";
+ const std::string sensFile = path + "/" + base + ".sens";
+ std::vector plyFiles = dir.getFilesWithSuffix(".ply");
+
+ const mat4f transform = readTransformFromAln(alnFile);
+
+ SensorData sd(sensFile);
+ if (sd.m_frames.size() == 0) throw MLIB_EXCEPTION("no frames found in the sensor file");
+ sd.applyTransform(transform);
+
+ { //save out transformed
+ for (const std::string& plyFile : plyFiles) {
+ MeshDataf mesh = MeshIOf::loadFromFile(dir.getPath() + "/" + plyFile);
+ mesh.applyTransform(transform);
+ MeshIOf::saveToFile(dir.getPath() + "/" + plyFile, mesh);
+ }
+ sd.applyTransform(transform);
+ sd.saveToFile(sensFile);
+ pf.aligned = true; //it's now aligned
+ pf.saveToFile(processedFile);
+ }
+ }
+
+
+private:
+};
\ No newline at end of file
diff --git a/Alignment/src/globalAppState.h b/Alignment/src/globalAppState.h
new file mode 100644
index 0000000..1ff697b
--- /dev/null
+++ b/Alignment/src/globalAppState.h
@@ -0,0 +1,72 @@
+#pragma once
+
+#ifndef _GLOBAL_APP_STATE_H_
+#define _GLOBAL_APP_STATE_H_
+
+#include "mLibInclude.h"
+
+#define X_GLOBAL_APP_STATE_FIELDS \
+ X(std::string, s_inputTestFile) \
+ X(std::string, s_sourceDirectory) \
+ X(std::vector, s_methods)
+
+
+#ifndef VAR_NAME
+#define VAR_NAME(x) #x
+#endif
+
+#define checkSizeArray(a, d)( (((sizeof a)/(sizeof a[0])) >= d))
+
+class GlobalAppState
+{
+public:
+
+#define X(type, name) type name;
+ X_GLOBAL_APP_STATE_FIELDS
+#undef X
+
+ //! sets the parameter file and reads
+ void readMembers(const ParameterFile& parameterFile) {
+ m_ParameterFile = parameterFile;
+ readMembers();
+ }
+
+ //! reads all the members from the given parameter file (could be called for reloading)
+ void readMembers() {
+#define X(type, name) \
+ if (!m_ParameterFile.readParameter(std::string(#name), name)) {MLIB_WARNING(std::string(#name).append(" ").append("uninitialized")); name = type();}
+ X_GLOBAL_APP_STATE_FIELDS
+#undef X
+ m_bIsInitialized = true;
+ }
+
+ void print() const {
+#define X(type, name) \
+ std::cout << #name " = " << name << std::endl;
+ X_GLOBAL_APP_STATE_FIELDS
+#undef X
+ }
+
+ static GlobalAppState& get() {
+ static GlobalAppState s;
+ return s;
+ }
+
+
+ //! constructor
+ GlobalAppState() {
+ m_bIsInitialized = false;
+ }
+
+ //! destructor
+ ~GlobalAppState() {
+ }
+
+
+
+private:
+ bool m_bIsInitialized;
+ ParameterFile m_ParameterFile;
+};
+
+#endif
\ No newline at end of file
diff --git a/Alignment/src/mLibInclude.h b/Alignment/src/mLibInclude.h
new file mode 100644
index 0000000..4ea883d
--- /dev/null
+++ b/Alignment/src/mLibInclude.h
@@ -0,0 +1,16 @@
+#ifndef _MLIB_INCLUDE_H_
+#define _MLIB_INCLUDE_H_
+
+#ifdef _DEBUG
+#define MLIB_ERROR_CHECK
+#endif
+
+#include
+#include
+#include
+#include
+#include
+
+using namespace ml;
+
+#endif
\ No newline at end of file
diff --git a/Alignment/src/mLibSource.cpp b/Alignment/src/mLibSource.cpp
new file mode 100644
index 0000000..f836f68
--- /dev/null
+++ b/Alignment/src/mLibSource.cpp
@@ -0,0 +1,7 @@
+
+#include "main.h"
+
+#include "mLibCore.cpp"
+#include "mLibLodePNG.cpp"
+#include "mLibDepthCamera.cpp"
+//#include "mLibZLib.cpp"
\ No newline at end of file
diff --git a/Alignment/src/main.cpp b/Alignment/src/main.cpp
new file mode 100644
index 0000000..fdbe6f8
--- /dev/null
+++ b/Alignment/src/main.cpp
@@ -0,0 +1,62 @@
+
+#include "stdafx.h"
+
+#include "main.h"
+#include "alignment.h"
+
+void alignScan(const std::string& sceneFolder, bool forceRealign = false)
+{
+ std::cout << "aligning: " << sceneFolder << std::endl;
+ Alignment::alignScan(sceneFolder, forceRealign);
+}
+
+void alignScanFromAlnFile(const std::string& sceneFolder)
+{
+ std::cout << "aligning: " << sceneFolder << std::endl;
+ Alignment::alignScanFromAlnFile(sceneFolder);
+}
+
+
+
+void alignDirectory(const std::string& path, bool forceRealign = false) {
+ Directory dir(path);
+ std::vector scenes = dir.getDirectories();
+ std::sort(scenes.begin(), scenes.end());
+ for (size_t i = 0; i < scenes.size(); i++) {
+ const std::string& scene = scenes[i];
+ const std::string sceneFolder = path + scene;
+ alignScan(sceneFolder);
+ //break;
+ //if (i >= 20) break;
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try {
+ if (argc == 2) { //converts a specific scan given by the command line argument
+ std::string stagingFolder(argv[1]);
+ alignScan(stagingFolder);
+ }
+ else {
+ throw MLIB_EXCEPTION("requires the path as a command line argument");
+ }
+ }
+ catch (const std::exception& e)
+ {
+ MessageBoxA(NULL, e.what(), "Exception caught", MB_ICONERROR);
+ exit(EXIT_FAILURE);
+ }
+ catch (...)
+ {
+ MessageBoxA(NULL, "UNKNOWN EXCEPTION", "Exception caught", MB_ICONERROR);
+ exit(EXIT_FAILURE);
+ }
+
+ //std::cout << "" << std::endl;
+ //getchar();
+
+ return 0;
+}
+
+
diff --git a/Alignment/src/main.h b/Alignment/src/main.h
new file mode 100644
index 0000000..9e593e5
--- /dev/null
+++ b/Alignment/src/main.h
@@ -0,0 +1,9 @@
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "stdafx.h"
diff --git a/Alignment/src/planeExtract.h b/Alignment/src/planeExtract.h
new file mode 100644
index 0000000..3db2dbb
--- /dev/null
+++ b/Alignment/src/planeExtract.h
@@ -0,0 +1,203 @@
+
+#pragma once
+
+#include "stdafx.h"
+
+
+struct Point {
+ Planef plane;
+ vec3f point;
+ size_t urIdx;
+};
+
+struct Cluster {
+ Cluster(const Point* init) {
+ m_points.push_back(init);
+ m_rep = *m_points.front();
+
+ sumNormal = init->plane.getNormal();
+ sumPoint = init->point;
+ }
+ void addPoint(const Point* p) {
+
+ m_points.push_back(p);
+
+ sumNormal += p->plane.getNormal();
+ sumPoint += p->point;
+
+ m_rep.plane = Planef(sumNormal.getNormalized(), sumPoint / (float)m_points.size());
+ }
+
+ bool check(const Point& p, float normalThresh, float distThresh) {
+ float d_norm = p.plane.getNormal() | m_rep.plane.getNormal();
+ float d_dist = m_rep.plane.distanceToPointAbs(p.point);
+
+ return (d_norm > normalThresh) && (d_dist < distThresh);
+ }
+
+ mat4f reComputeNormalAlignment() const {
+ std::vector points;
+ for (const Point* p : m_points) {
+ if (m_rep.plane.distanceToPointAbs(p->point) < 0.05f) {
+ points.push_back(p->point);
+ }
+ }
+ auto res = math::pointSetPCA(points);
+ mat4f m(res[0].first.getNormalized(), res[1].first.getNormalized(), res[2].first.getNormalized());
+ return m.getTranspose();
+ }
+
+ vec3f reComputeNormal() const {
+ std::vector points;
+ for (const Point* p : m_points) {
+ if (m_rep.plane.distanceToPointAbs(p->point) < 0.05f) {
+ points.push_back(p->point);
+ }
+ }
+ auto res = math::pointSetPCA(points);
+ mat3f m(res[0].first.getNormalized(), res[1].first.getNormalized(), res[2].first.getNormalized());
+ return m.zcol().getNormalized();
+ }
+
+ bool operator<(const Cluster& other) const {
+ return m_points.size() > other.m_points.size();
+ }
+
+ Point m_rep;
+ std::list m_points;
+
+ vec3f sumNormal;
+ vec3f sumPoint;
+};
+
+class PlaneExtract {
+public:
+ PlaneExtract(const MeshDataf& md) {
+ if (!md.hasNormals()) throw MLIB_EXCEPTION("need to compute normals first");
+
+ m_points.resize(md.m_Vertices.size());
+ for (size_t i = 0; i < md.m_Vertices.size(); i++) {
+ Point& p = m_points[i];
+ p.plane = Planef(md.m_Normals[i], md.m_Vertices[i]);
+ p.point = md.m_Vertices[i];
+ p.urIdx = i;
+ m_pointsRef.push_back(&m_points[i]);
+ }
+ }
+
+ void cluster(float normalThresh = 0.90f, float distThresh = 0.05f) {
+ for (const Point* p : m_pointsRef) {
+ bool foundCluster = false;
+ for (Cluster& c : m_clusters) {
+ if (c.check(*p, normalThresh, distThresh)) {
+ c.addPoint(p);
+ foundCluster = true;
+ break;
+ }
+ }
+ if (!foundCluster) {
+ m_clusters.push_back(Cluster(p));
+ }
+ }
+
+ m_clusters.sort();
+ }
+
+ void print(unsigned int topN = 10) const {
+ std::cout << m_points.size() << " points " << std::endl;
+ std::cout << m_clusters.size() << " clusters " << std::endl;
+ unsigned int i = 0;
+ for (const Cluster& c : m_clusters) {
+ if (i >= topN) break;
+ std::cout << "\t" << c.m_points.size() << std::endl;
+ i++;
+ }
+ }
+
+
+ const std::list getClusters() const {
+ return m_clusters;
+ }
+
+ void removeSmallClusters(size_t minSize = 500) {
+ for (std::list::iterator iter = m_clusters.begin(); iter != m_clusters.end();) {
+ if (iter->m_points.size() < minSize) {
+ iter = m_clusters.erase(iter);
+ }
+ else {
+ iter++;
+ }
+ }
+ }
+
+ //threshold is 10cm by default
+ void removeNonBoundingClusters(float distThresh, unsigned int numthresh) {
+ for (std::list::iterator iter = m_clusters.begin(); iter != m_clusters.end();) {
+ if (!isBoundingCluster(*iter, distThresh, numthresh)) {
+ iter = m_clusters.erase(iter);
+ }
+ else {
+ iter++;
+ }
+ }
+ }
+
+ //check whether there are points behind the plane -- if so then return false
+ bool isBoundingCluster(const Cluster& c, float distThresh, unsigned int numThresh) const {
+ unsigned int countBehind = 0;
+ for (size_t i = 0; i < m_points.size(); i++) {
+ const float d = c.m_rep.plane.distanceToPoint(m_points[i].point);
+ if (d < -distThresh) countBehind++;
+ }
+ if (countBehind > numThresh) return false;
+ else return true;
+ }
+
+ void saveColoredPlanes(const std::string& filename, const MeshDataf& md, unsigned int topN = 0) {
+ topN = (unsigned int)std::min(topN, m_clusters.size());
+
+ MeshDataf mesh = md;
+
+ if (mesh.m_Colors.size() != mesh.m_Vertices.size()) {
+ mesh.m_Colors.resize(mesh.m_Vertices.size());
+ }
+
+ size_t i = 0;
+ for (const Cluster& c : m_clusters) {
+ RGBColor color = RGBColor::randomColor();
+ for (const Point* p : c.m_points) {
+ mesh.m_Colors[p->urIdx] = color;
+ }
+
+ i++;
+ if (topN != 0 && i >= topN) {
+ break;
+ }
+ }
+
+ MeshIOf::saveToFile(filename, mesh);
+ }
+
+
+ void saveColoredPlane(const std::string& filename, const Cluster& c, const MeshDataf& md, const RGBColor& color = RGBColor::randomColor()) {
+
+ MeshDataf mesh = md;
+
+ if (mesh.m_Colors.size() != mesh.m_Vertices.size()) {
+ mesh.m_Colors.resize(mesh.m_Vertices.size());
+ }
+
+ for (const Point* p : c.m_points) {
+ mesh.m_Colors[p->urIdx] = color;
+ }
+
+ MeshIOf::saveToFile(filename, mesh);
+ }
+
+private:
+
+
+ std::vector m_points;
+ std::list m_pointsRef;
+ std::list m_clusters;
+};
diff --git a/Alignment/src/processedFile.h b/Alignment/src/processedFile.h
new file mode 100644
index 0000000..3930691
--- /dev/null
+++ b/Alignment/src/processedFile.h
@@ -0,0 +1,87 @@
+#pragma once
+
+
+#include "mLibInclude.h"
+
+#define X_PROCESSED_FILE_STATE_FIELDS \
+ X(bool, valid) \
+ X(unsigned int, heapFreeCount) \
+ X(unsigned int, numValidOptTransforms) \
+ X(unsigned int, numTransforms) \
+ X(bool, aligned)
+
+
+#ifndef VAR_NAME
+#define VAR_NAME(x) #x
+#endif
+
+#define checkSizeArray(a, d)( (((sizeof a)/(sizeof a[0])) >= d))
+
+class ProcessedFile
+{
+public:
+
+#define X(type, name) type name;
+ X_PROCESSED_FILE_STATE_FIELDS
+#undef X
+
+ //! sets the parameter file and reads
+ void readMembers(const ParameterFile& parameterFile) {
+ m_ParameterFile = parameterFile;
+ readMembers();
+ }
+
+ //! reads all the members from the given parameter file (could be called for reloading)
+ void readMembers() {
+ aligned = false;
+
+#define X(type, name) \
+ if (!m_ParameterFile.readParameter(std::string(#name), name) && std::string(#name) != "aligned") {MLIB_WARNING(std::string(#name).append(" ").append("uninitialized")); name = type();}
+ X_PROCESSED_FILE_STATE_FIELDS
+#undef X
+
+ m_bIsInitialized = true;
+ }
+
+ template
+ std::string makeString(const T& in) {
+ std::string ret = std::to_string(in);
+ return ret;
+ }
+ template <>
+ std::string makeString(const bool& in) {
+ if (in == true) return "true";
+ else return "false";
+ }
+
+ void saveToFile(const std::string& outFile) {
+ std::ofstream out(outFile);
+#define X(type, name) \
+ { out << #name << " = " << makeString(name) << std::endl; }
+ X_PROCESSED_FILE_STATE_FIELDS
+#undef X
+ }
+
+ void print() const {
+#define X(type, name) \
+ std::cout << #name " = " << name << std::endl;
+ X_PROCESSED_FILE_STATE_FIELDS
+#undef X
+ }
+
+
+ //! constructor
+ ProcessedFile() {
+ m_bIsInitialized = false;
+ }
+
+ //! destructor
+ ~ProcessedFile() {
+ }
+
+
+private:
+ bool m_bIsInitialized;
+ ParameterFile m_ParameterFile;
+};
+
diff --git a/Alignment/src/stdafx.cpp b/Alignment/src/stdafx.cpp
new file mode 100644
index 0000000..3f38672
--- /dev/null
+++ b/Alignment/src/stdafx.cpp
@@ -0,0 +1,11 @@
+// stdafx.cpp : source file that includes just the standard includes
+// VirtualScan.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#pragma warning (disable : 4996)
+
+#include "stdafx.h"
+
+#include "mLibSource.cpp"
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/Alignment/src/stdafx.h b/Alignment/src/stdafx.h
new file mode 100644
index 0000000..c695e5c
--- /dev/null
+++ b/Alignment/src/stdafx.h
@@ -0,0 +1,13 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include
+#include
+
+// TODO: reference additional headers your program requires here
+
+#include "mLibInclude.h"
\ No newline at end of file
diff --git a/AnnotationTools/Filter2dAnnotations/Filter2dAnnotations.cpp b/AnnotationTools/Filter2dAnnotations/Filter2dAnnotations.cpp
new file mode 100644
index 0000000..0f69b2b
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/Filter2dAnnotations.cpp
@@ -0,0 +1,440 @@
+// EvaluateAnnotations.cpp : Defines the entry point for the console application.
+//
+
+#include "stdafx.h"
+#include
+#include "GlobalDefines.h"
+#include "MatrixConversion.h"
+#include "../common/json.h"
+#include "../common/Segmentation.h"
+#include "../common/Aggregation.h"
+#include "LabelUtil.h"
+
+extern "C" void convertDepthFloatToCameraSpaceFloat4(float4* d_output, float* d_input, float4x4 intrinsicsInv, unsigned int width, unsigned int height);
+extern "C" void computeNormals(float4* d_output, float4* d_input, unsigned int width, unsigned int height);
+extern "C" void resampleFloatMap(float* d_colorMapResampledFloat, unsigned int outputWidth, unsigned int outputHeight,
+ float* d_colorMapFloat, unsigned int inputWidth, unsigned int inputHeight);
+extern "C" void resampleUCharMap(unsigned char* d_MapResampled, unsigned int outputWidth, unsigned int outputHeight,
+ unsigned char* d_Map, unsigned int inputWidth, unsigned int inputHeight);
+extern "C" void gaussFilterFloat4Map(float4* d_output, float4* d_input, float sigmaD, float sigmaR, unsigned int width, unsigned int height);
+extern "C" void bilateralFilterFloatMap(float* d_output, float* d_input, float sigmaD, float sigmaR, unsigned int width, unsigned int height);
+extern "C" void bilateralFilterFloat4Map(float4* d_output, float4* d_input, float sigmaD, float sigmaR, unsigned int width, unsigned int height);
+extern "C" void filterAnnotations(unsigned char* d_outputInstance, const unsigned char* d_inputInstance,
+ const float* d_depth, const float* d_intensity, const unsigned char* d_instanceToIdx,
+ const unsigned char* d_idxToInstance, float* d_vote,
+ int structureSize, int width, int height, float sigmaD, float sigmaR, float intensityScale);
+extern "C" void convertInstanceToLabel(unsigned short* d_outputLabel, const unsigned char* d_inputInstance,
+ const unsigned short* d_instanceToLabel, unsigned int width, unsigned int height);
+
+struct FilterData {
+ FilterData() {
+ d_instanceToIdx = NULL;
+ d_idxToInstance = NULL;
+ d_vote = NULL;
+ d_instanceToLabel = NULL;
+ d_depth = NULL;
+ d_intensity = NULL;
+ d_instance = NULL;
+ d_instanceHelper = NULL;
+ d_label = NULL;
+ d_depthHelper = NULL;
+ d_intensityHelper = NULL;
+ }
+ void alloc(unsigned int width, unsigned int height) {
+ MLIB_CUDA_SAFE_CALL(cudaMalloc(&d_instanceToIdx, sizeof(unsigned char)*MAX_NUM_LABELS_PER_SCENE));
+ MLIB_CUDA_SAFE_CALL(cudaMalloc(&d_idxToInstance, sizeof(unsigned char)*MAX_NUM_LABELS_PER_SCENE));
+ MLIB_CUDA_SAFE_CALL(cudaMalloc(&d_instanceToLabel, sizeof(unsigned short)*MAX_NUM_LABELS_PER_SCENE));
+ MLIB_CUDA_SAFE_CALL(cudaMalloc(&d_vote, sizeof(float)*width*height*MAX_NUM_LABELS_PER_SCENE));
+ MLIB_CUDA_SAFE_CALL(cudaMalloc(&d_depth, sizeof(float)*width*height));
+ MLIB_CUDA_SAFE_CALL(cudaMalloc(&d_intensity, sizeof(float)*width*height));
+ MLIB_CUDA_SAFE_CALL(cudaMalloc(&d_depthHelper, sizeof(float)*width*height));
+ MLIB_CUDA_SAFE_CALL(cudaMalloc(&d_intensityHelper, sizeof(float)*width*height));
+ MLIB_CUDA_SAFE_CALL(cudaMalloc(&d_instance, sizeof(unsigned char)*width*height));
+ MLIB_CUDA_SAFE_CALL(cudaMalloc(&d_instanceHelper, sizeof(unsigned char)*width*height));
+ MLIB_CUDA_SAFE_CALL(cudaMalloc(&d_label, sizeof(unsigned short)*width*height));
+ }
+ void init(const std::vector& objectIdsToIdx, const std::vector& idxToObjectIds, const std::vector& objectIdsToLabel) {
+ //initialize
+ MLIB_CUDA_SAFE_CALL(cudaMemcpy(d_instanceToIdx, objectIdsToIdx.data(), sizeof(unsigned char)*MAX_NUM_LABELS_PER_SCENE, cudaMemcpyHostToDevice));
+ MLIB_CUDA_SAFE_CALL(cudaMemcpy(d_idxToInstance, idxToObjectIds.data(), sizeof(unsigned char)*MAX_NUM_LABELS_PER_SCENE, cudaMemcpyHostToDevice));
+ MLIB_CUDA_SAFE_CALL(cudaMemcpy(d_instanceToLabel, objectIdsToLabel.data(), sizeof(unsigned short)*MAX_NUM_LABELS_PER_SCENE, cudaMemcpyHostToDevice));
+ }
+ void free() {
+ MLIB_CUDA_SAFE_FREE(d_instanceToIdx);
+ MLIB_CUDA_SAFE_FREE(d_idxToInstance);
+ MLIB_CUDA_SAFE_FREE(d_instanceToLabel);
+ MLIB_CUDA_SAFE_FREE(d_vote);
+ MLIB_CUDA_SAFE_FREE(d_depth);
+ MLIB_CUDA_SAFE_FREE(d_intensity);
+ MLIB_CUDA_SAFE_FREE(d_depthHelper);
+ MLIB_CUDA_SAFE_FREE(d_intensityHelper);
+ MLIB_CUDA_SAFE_FREE(d_instance);
+ MLIB_CUDA_SAFE_FREE(d_instanceHelper);
+ MLIB_CUDA_SAFE_FREE(d_label);
+ }
+
+ unsigned char* d_instanceToIdx, *d_idxToInstance; float* d_vote; unsigned short* d_instanceToLabel;
+ float* d_depth, *d_intensity; unsigned char* d_instance, *d_instanceHelper; unsigned short* d_label;
+ float* d_depthHelper, *d_intensityHelper;
+};
+
+std::vector readScenesFromFile(const std::string& filename);
+void process(FilterData& filterData, std::string path, std::string scanNetPath, std::string outputPath, const std::string& name, bool printDebugOutput);
+void processSegs(std::string path, std::string scanNetPath, std::string outputPath, const std::string& name);
+
+void debugVis(const std::string& rawPath, const std::string& filtPath, const std::string& scene, const std::string& scanNetPath, const std::string& outDir);
+
+int _tmain(int argc, _TCHAR* argv[])
+{
+ try {
+ //-------Fill in the paths accordingly here
+ const bool bPrintDebugOutput = false;
+ const std::string scanNetDir = "../../data/scans/";
+ const std::string dataPath = "../annotations-2d/";
+ const std::string outputPath = "../annotations-2d-filtered/";
+ const std::string sceneListFile = "../../Tasks/Benchmark/scannet_train.txt";
+ LabelUtil::get().init("../../data/tasks/scannet-labels.combined.tsv");
+ //-------
+
+ if (!util::directoryExists(scanNetDir) || !util::directoryExists(dataPath))
+ throw MLIB_EXCEPTION("input data dir(s) do not exist");
+ if (!sceneListFile.empty() && !util::fileExists(sceneListFile))
+ throw MLIB_EXCEPTION("scene list file (" + sceneListFile + ") does not exist");
+
+ if (!util::directoryExists(outputPath)) util::makeDirectory(outputPath);
+
+ Directory annotationDir(dataPath);
+ std::vector scenes;
+ if (sceneListFile.empty())
+ scenes = annotationDir.getDirectories();
+ else
+ scenes = readScenesFromFile(sceneListFile);
+
+ std::cout << "found " << scenes.size() << " scenes" << std::endl;
+ unsigned int counter = 0;
+ FilterData filterData; filterData.alloc(1296, 968); //max width/height
+ for (const std::string& scene : scenes) {
+ if (!util::directoryExists(dataPath + scene)) continue;
+ Timer t;
+ process(filterData, dataPath + scene, scanNetDir, outputPath + scene, scene, bPrintDebugOutput);
+ t.stop(); std::cout << "[" << counter << " | " << scenes.size() << "] time for scene: " << t.getElapsedTime() << " s" << std::endl;
+ counter++;
+ }
+ filterData.free();
+ std::cout << std::endl << "processed " << counter << " scenes" << std::endl;
+ }
+ catch (MLibException& e)
+ {
+ std::stringstream ss;
+ ss << "exception caught:" << e.what() << std::endl;
+ std::cout << ss.str() << std::endl;
+ }
+ std::cout << "done done done" << std::endl;
+ //getchar();
+ return 0;
+}
+
+std::vector readScenesFromFile(const std::string& filename)
+{
+ std::vector scenes;
+ std::ifstream s(filename); std::string line;
+ while (std::getline(s, line))
+ scenes.push_back(line);
+ return scenes;
+}
+
+void visualizeAnnotations(const std::string& prefix, const BaseImage& instanceImage, const BaseImage& labelImage = BaseImage(),
+ bool printLegend = false, const Aggregation& agg = Aggregation())
+{
+ static std::unordered_map colormap;
+ for (const auto& p : instanceImage) {
+ if (p.value != 0 && colormap.find(p.value) == colormap.end()) {
+ RGBColor c = RGBColor::randomColor();
+ while (vec3f(c).length() < 0.05f)
+ c = RGBColor::randomColor();
+ colormap[p.value] = vec3uc(c.x, c.y, c.z);
+ }
+ }
+ if (labelImage.getNumPixels() > 0) {
+ for (const auto& p : labelImage) {
+ if (p.value != 0 && colormap.find(p.value) == colormap.end()) {
+ RGBColor c = RGBColor::randomColor();
+ while (vec3f(c).length() < 0.05f)
+ c = RGBColor::randomColor();
+ colormap[p.value] = vec3uc(c.x, c.y, c.z);
+ }
+ }
+ }
+ ColorImageR8G8B8 visInstance(instanceImage.getDimensions()), visLabel(labelImage.getDimensions());
+ for (unsigned int y = 0; y < instanceImage.getHeight(); y++) {
+ for (unsigned int x = 0; x < instanceImage.getWidth(); x++) {
+ const auto instance = instanceImage(x, y);
+ if (instance == 0) visInstance(x, y) = vec3uc(0, 0, 0);
+ else visInstance(x, y) = colormap[instance];
+ if (labelImage.getNumPixels() > 0) {
+ const auto label = labelImage(x, y);
+ if (label == 0) visLabel(x, y) = vec3uc(0, 0, 0);
+ else visLabel(x, y) = colormap[label];
+ }
+ }
+ }
+ FreeImageWrapper::saveImage(prefix + "-instance.png", visInstance);
+ if (labelImage.getNumPixels() > 0) FreeImageWrapper::saveImage(prefix + "-label.png", visLabel);
+
+ if (printLegend) {
+ std::unordered_map> instanceColors;
+ std::unordered_map> labelColors;
+ const auto& objectIdToLabels = agg.getObjectIdsToLabels();
+ bool bRaw = util::endsWith(prefix, "raw");
+ for (const auto& p : instanceImage) {
+ if (p.value != 0) {
+ const unsigned char inst = p.value - 1;
+ const auto it = instanceColors.find(inst);
+ if (it == instanceColors.end()) {
+ const auto it2 = objectIdToLabels.find(inst);
+ instanceColors[inst] = std::make_pair(it2->second, colormap[inst+1]);
+ if (labelImage(p.x, p.y) > 0) {
+ std::string labelName;
+ bool valid = LabelUtil::get().getLabelForId(labelImage(p.x, p.y), labelName);
+ MLIB_ASSERT(valid);
+ labelColors[labelImage(p.x, p.y)] = std::make_pair(labelName, colormap[labelImage(p.x, p.y)]);
+
+ if (bRaw && labelName != it2->second)
+ std::cout << "ERROR: inconsistent instance/label" << std::endl;
+ }
+ }
+ }
+ }
+ const std::string legendPrefix = prefix + "_legend-";
+ for (const auto& c : instanceColors) {
+ ColorImageR8G8B8 image(100, 100);
+ image.setPixels(c.second.second);
+ FreeImageWrapper::saveImage(legendPrefix + "instance_" + c.second.first + ".png", image);
+ }
+ for (const auto& c : labelColors) {
+ ColorImageR8G8B8 image(100, 100);
+ image.setPixels(c.second.second);
+ FreeImageWrapper::saveImage(legendPrefix + "label_" + c.second.first + ".png", image);
+ }
+ }
+}
+
+ColorImageR32 convertToGrayscale(const ColorImageR8G8B8& color)
+{
+ ColorImageR32 res(color.getDimensions());
+ for (const auto& p : color) {
+ float v = (0.299f*p.value.x + 0.587f*p.value.y + 0.114f*p.value.z) / 255.0f;
+ res(p.x, p.y) = v;
+ }
+ return res;
+}
+
+void convertToGrayscale(const vec3uc* color, unsigned int width, unsigned int height, ColorImageR32& intensity)
+{
+ intensity.allocate(width, height);
+ const float inv = 1.0f / 255.0f;
+ for (unsigned int y = 0; y < height; y++) {
+ for (unsigned int x = 0; x < width; x++) {
+ const vec3uc& c = color[y * width + x];
+ float v = (0.299f*c.x + 0.587f*c.y + 0.114f*c.z) * inv;
+ intensity(x, y) = v;
+ }
+ }
+}
+
+void convertToFloat(const unsigned short* depth, unsigned int width, unsigned int height, DepthImage32& depthImage)
+{
+ depthImage.allocate(width, height);
+ const float inv = 1.0f / 255.0f;
+ for (unsigned int y = 0; y < height; y++) {
+ for (unsigned int x = 0; x < width; x++) {
+ const unsigned short d = depth[y*width + x];
+ if (d == 0) depthImage(x, y) = -std::numeric_limits::infinity();
+ else depthImage(x, y) = (float)d * 0.001f;
+ }
+ }
+}
+
+void process(FilterData& filterData, std::string path, std::string scanNetPath, std::string outputPath, const std::string& name, bool printDebugOutput)
+{
+ if (!(path.back() == '\\' || path.back() == '/')) path.push_back('/');
+ if (!(scanNetPath.back() == '\\' || scanNetPath.back() == '/')) scanNetPath.push_back('/');
+ if (!(outputPath.back() == '\\' || outputPath.back() == '/')) outputPath.push_back('/');
+ const std::string instancePath = path + "instance/";
+ const std::string labelPath = path + "label/";
+ if (!util::directoryExists(labelPath) || !util::directoryExists(instancePath))
+ throw MLIB_EXCEPTION("instance/label dir does not exist for " + path);
+ const std::string outputInstancePath = outputPath + "instance/";
+ const std::string outputLabelPath = outputPath + "label/";
+ std::cout << path << std::endl;
+ SensorData sd(scanNetPath + name + "/" + name + ".sens");
+ if (util::directoryExists(outputInstancePath) && util::directoryExists(outputLabelPath)) {
+ Directory outInst(outputInstancePath);
+ Directory outLabel(outputLabelPath);
+ if (outInst.getFiles().size() == sd.m_frames.size() && outLabel.getFiles().size() == sd.m_frames.size()) {
+ std::cout << " ==> skipping, already exists" << std::endl;
+ return;
+ }
+ }
+ Aggregation agg; agg.loadFromJSONFile(scanNetPath + name + "/" + name + ".aggregation.json");
+ const auto& objecIdsToLabelNames = agg.getObjectIdsToLabels();
+
+ if (!util::directoryExists(outputPath)) util::makeDirectory(outputPath);
+ if (!util::directoryExists(outputInstancePath)) util::makeDirectory(outputInstancePath);
+ if (!util::directoryExists(outputLabelPath)) util::makeDirectory(outputLabelPath);
+ const std::string outDebugPath = "debug/" + name + "/";
+ if (printDebugOutput && !util::directoryExists(outDebugPath)) util::makeDirectory(outDebugPath);
+
+ const std::vector filterWidths = { 320, sd.m_colorWidth };
+ const std::vector filterHeights = { 240, sd.m_colorHeight };
+ const std::vector filterRadii = { 12, 10 };
+ const std::vector intensityScales = { 10.0f, 4.0f }; //higher respects edges better but edges are rough and sometimes ends up cutting things that overreach too far
+ MLIB_ASSERT(filterWidths.size() == filterHeights.size() && filterWidths.size() == intensityScales.size());
+ const unsigned int numFiltIters = (unsigned int)filterWidths.size();
+
+ std::vector objectIdsToIdx(MAX_NUM_LABELS_PER_SCENE, 255), idxToObjectIds(MAX_NUM_LABELS_PER_SCENE, 255);
+ std::vector objectIdsToLabel(MAX_NUM_LABELS_PER_SCENE, 65535);
+ unsigned char idx = 1;
+ objectIdsToIdx[0] = 0; idxToObjectIds[0] = 0; objectIdsToLabel[0] = 0;
+ for (const auto& a : objecIdsToLabelNames) { //object ids are 0-indexed so add 1
+ unsigned short label;
+ bool bValid = LabelUtil::get().getIdForLabel(a.second, label);
+ if (!bValid) {
+ //std::cout << "warning: no label id for " << a.second << std::endl;
+ label = 0;
+ }
+ objectIdsToLabel[a.first + 1] = label;
+ objectIdsToIdx[a.first + 1] = idx;
+ idxToObjectIds[idx] = a.first + 1;
+ idx++;
+ }
+ filterData.init(objectIdsToIdx, idxToObjectIds, objectIdsToLabel);
+
+ Directory dir(labelPath);
+ const auto& files = dir.getFiles(); unsigned int _idx = 0;
+ for (const auto& f : files) {
+ const unsigned int frameIdx = util::convertTo(util::removeExtensions(f));
+ if (sd.m_frames[frameIdx].getCameraToWorld()[0] == -std::numeric_limits::infinity()) {
+ BaseImage labelImage(sd.m_colorWidth, sd.m_colorHeight); BaseImage instanceImage(sd.m_colorWidth, sd.m_colorHeight);
+ labelImage.setPixels(0); instanceImage.setPixels(0);
+ FreeImageWrapper::saveImage(outputInstancePath + f, instanceImage);
+ FreeImageWrapper::saveImage(outputLabelPath + f, labelImage);
+ continue;
+ }
+ DepthImage32 depth; ColorImageR32 intensity;
+ {
+ unsigned short* depthData = sd.decompressDepthAlloc(frameIdx);
+ vec3uc* colorData = sd.decompressColorAlloc(frameIdx);
+ convertToFloat(depthData, sd.m_depthWidth, sd.m_depthHeight, depth);
+ convertToGrayscale(colorData, sd.m_colorWidth, sd.m_colorHeight, intensity); //could also move to gpu
+ std::free(depthData); std::free(colorData);
+ }
+ MLIB_CUDA_SAFE_CALL(cudaMemcpy(filterData.d_depth, depth.getData(), sizeof(float)*depth.getNumPixels(), cudaMemcpyHostToDevice));
+ MLIB_CUDA_SAFE_CALL(cudaMemcpy(filterData.d_intensity, intensity.getData(), sizeof(float)*intensity.getNumPixels(), cudaMemcpyHostToDevice));
+ bilateralFilterFloatMap(filterData.d_intensityHelper, filterData.d_intensity, 6.0f, 0.1f, intensity.getWidth(), intensity.getHeight());
+ bilateralFilterFloatMap(filterData.d_depthHelper, filterData.d_depth, 2.0f, 0.1f, depth.getWidth(), depth.getHeight());
+
+ const std::string instanceFile = instancePath + f;
+ const std::string labelFile = labelPath + f;
+ BaseImage labelImage; BaseImage instanceImage;
+ FreeImageWrapper::loadImage(instanceFile, instanceImage);
+ FreeImageWrapper::loadImage(labelFile, labelImage);
+ MLIB_CUDA_SAFE_CALL(cudaMemcpy(filterData.d_instanceHelper, instanceImage.getData(), sizeof(unsigned char)*instanceImage.getNumPixels(), cudaMemcpyHostToDevice));
+
+ if (printDebugOutput && frameIdx % 100 == 0) {//debug vis
+ FreeImageWrapper::saveImage(outDebugPath + std::to_string(frameIdx) + "_depth.png", ColorImageR32G32B32(depth));
+ FreeImageWrapper::saveImage(outDebugPath + std::to_string(frameIdx) + "_intensity.png", intensity);
+ MLIB_CUDA_SAFE_CALL(cudaMemcpy(intensity.getData(), filterData.d_intensityHelper, sizeof(float)*intensity.getNumPixels(), cudaMemcpyDeviceToHost));
+ FreeImageWrapper::saveImage(outDebugPath + std::to_string(frameIdx) + "_intensity-filt.png", intensity);
+ visualizeAnnotations(outDebugPath + std::to_string(frameIdx) + "_orig", instanceImage, labelImage);
+ }//debug vis
+
+ //t.start();
+ unsigned int curDepthWidth = depth.getWidth(), curDepthHeight = depth.getHeight();
+ unsigned int curColorWidth = intensity.getWidth(), curColorHeight = intensity.getHeight();
+ if (filterWidths.front() != instanceImage.getWidth())
+ resampleUCharMap(filterData.d_instance, filterWidths.front(), filterHeights.front(), filterData.d_instanceHelper, instanceImage.getWidth(), instanceImage.getHeight());
+ for (unsigned int iter = 0; iter < numFiltIters; iter++) {
+ //resample depth
+ if (curDepthWidth != filterWidths[iter]) {
+ if (filterWidths[iter] == sd.m_depthWidth) {
+ if (iter + 1 == numFiltIters)
+ std::swap(filterData.d_depth, filterData.d_depthHelper);
+ else
+ MLIB_CUDA_SAFE_CALL(cudaMemcpy(filterData.d_depth, depth.getData(), sizeof(float)*depth.getNumPixels(), cudaMemcpyHostToDevice));
+ }
+ else {
+ resampleFloatMap(filterData.d_depth, filterWidths[iter], filterHeights[iter], filterData.d_depthHelper, depth.getWidth(), depth.getHeight());
+ }
+ curDepthWidth = filterWidths[iter];
+ curDepthHeight = filterHeights[iter];
+ }
+ //resample color
+ if (curColorWidth != filterWidths[iter]) {
+ if (filterWidths[iter] == sd.m_colorWidth) {
+ if (iter + 1 == numFiltIters)
+ std::swap(filterData.d_intensity, filterData.d_intensityHelper);
+ else
+ MLIB_CUDA_SAFE_CALL(cudaMemcpy(filterData.d_intensity, intensity.getData(), sizeof(float)*intensity.getNumPixels(), cudaMemcpyHostToDevice));
+ }
+ else {
+ resampleFloatMap(filterData.d_intensity, filterWidths[iter], filterHeights[iter], filterData.d_intensityHelper, intensity.getWidth(), intensity.getHeight());
+ }
+ curColorWidth = filterWidths[iter];
+ curColorHeight = filterHeights[iter];
+ }
+ filterAnnotations(filterData.d_instanceHelper, filterData.d_instance, filterData.d_depth, filterData.d_intensity,
+ filterData.d_instanceToIdx, filterData.d_idxToInstance, filterData.d_vote,
+ filterRadii[iter], filterWidths[iter], filterHeights[iter], 5.0f, 0.1f, intensityScales[iter]);
+
+ if (iter + 1 == numFiltIters)
+ std::swap(filterData.d_instanceHelper, filterData.d_instance); //result is in instance
+ else
+ resampleUCharMap(filterData.d_instance, filterWidths[iter + 1], filterHeights[iter + 1], filterData.d_instanceHelper, filterWidths[iter], filterHeights[iter]);
+ }
+ convertInstanceToLabel(filterData.d_label, filterData.d_instance, filterData.d_instanceToLabel, filterWidths.back(), filterHeights.back());
+ MLIB_CUDA_SAFE_CALL(cudaMemcpy(instanceImage.getData(), filterData.d_instance, sizeof(unsigned char)*instanceImage.getNumPixels(), cudaMemcpyDeviceToHost));
+ MLIB_CUDA_SAFE_CALL(cudaMemcpy(labelImage.getData(), filterData.d_label, sizeof(unsigned short)*labelImage.getNumPixels(), cudaMemcpyDeviceToHost));
+
+ //save out
+ FreeImageWrapper::saveImage(outputInstancePath + f, instanceImage);
+ FreeImageWrapper::saveImage(outputLabelPath + f, labelImage);
+
+ if (printDebugOutput && frameIdx % 100 == 0) {//debug vis
+ visualizeAnnotations(outDebugPath + std::to_string(frameIdx) + "_filt", instanceImage, labelImage);
+ std::cout << "waiting..." << std::endl;
+ getchar();
+ }
+ if (_idx % 10 == 0 || _idx + 1 == files.size())
+ std::cout << "\r[ " << _idx << " | " << files.size() << " ]";
+ ++_idx;
+ }
+ std::cout << std::endl;
+}
+
+void debugVis(const std::string& rawPath, const std::string& filtPath, const std::string& scene, const std::string& scanNetPath, const std::string& outDir)
+{
+ const unsigned int frameIdx = 400;//0;
+ const std::string rawInstanceFile = rawPath + scene + "/instance/" + std::to_string(frameIdx) + ".png";
+ const std::string rawLabelFile = rawPath + scene + "/label/" + std::to_string(frameIdx) + ".png";
+ const std::string filtInstanceFile = filtPath + scene + "/instance/" + std::to_string(frameIdx) + ".png";
+ const std::string filtLabelFile = filtPath + scene + "/label/" + std::to_string(frameIdx) + ".png";
+
+ Aggregation agg; agg.loadFromJSONFile(scanNetPath + scene + "/" + scene + ".aggregation.json");
+ SensorData sd(scanNetPath + scene + "/" + scene + ".sens");
+ DepthImage32 depth = sd.computeDepthImage(frameIdx);
+ ColorImageR8G8B8 color = sd.computeColorImage(frameIdx);
+
+ BaseImage rawInstance, filtInstance;
+ BaseImage rawLabel, filtLabel;
+ FreeImageWrapper::loadImage(rawInstanceFile, rawInstance);
+ FreeImageWrapper::loadImage(filtInstanceFile, filtInstance);
+ FreeImageWrapper::loadImage(rawLabelFile, rawLabel);
+ FreeImageWrapper::loadImage(filtLabelFile, filtLabel);
+
+ visualizeAnnotations(outDir + "raw", rawInstance, rawLabel, true, agg);
+ visualizeAnnotations(outDir + "filt", filtInstance, filtLabel);
+ FreeImageWrapper::saveImage(outDir + "depth.png", ColorImageR32G32B32(depth));
+ FreeImageWrapper::saveImage(outDir + "color.png", color);
+}
+
diff --git a/AnnotationTools/Filter2dAnnotations/Filter2dAnnotations.sln b/AnnotationTools/Filter2dAnnotations/Filter2dAnnotations.sln
new file mode 100644
index 0000000..f48e399
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/Filter2dAnnotations.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Filter2dAnnotations", "Filter2dAnnotations.vcxproj", "{5427D3D9-F7E5-4625-A73D-9CF84E22FF06}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5427D3D9-F7E5-4625-A73D-9CF84E22FF06}.Debug|x64.ActiveCfg = Debug|x64
+ {5427D3D9-F7E5-4625-A73D-9CF84E22FF06}.Debug|x64.Build.0 = Debug|x64
+ {5427D3D9-F7E5-4625-A73D-9CF84E22FF06}.Release|x64.ActiveCfg = Release|x64
+ {5427D3D9-F7E5-4625-A73D-9CF84E22FF06}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/AnnotationTools/Filter2dAnnotations/Filter2dAnnotations.vcxproj b/AnnotationTools/Filter2dAnnotations/Filter2dAnnotations.vcxproj
new file mode 100644
index 0000000..abfce9e
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/Filter2dAnnotations.vcxproj
@@ -0,0 +1,127 @@
+
+
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {5427D3D9-F7E5-4625-A73D-9CF84E22FF06}
+ Win32Proj
+ Filter2dAnnotations
+
+
+
+ Application
+ true
+ v120
+ Unicode
+
+
+ Application
+ false
+ v120
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ ../../external/mLib/include;../../../mLibExternal/include;../../external/cutil/inc;$(IncludePath)
+ ../../../mLibExternal/libsWindows/lib64;$(LibraryPath)
+
+
+ false
+ ../../external/mLib/include;../../../mLibExternal/include;../../external/cutil/inc;$(IncludePath)
+ ../../../mLibExternal/libsWindows/lib64;$(LibraryPath)
+
+
+
+ Use
+ Level3
+ Disabled
+ WIN32;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ FreeImage.lib;cudart.lib;cublas.lib;%(AdditionalDependencies)
+
+
+ compute_35,sm_35
+
+
+
+
+ Level3
+ Use
+ MaxSpeed
+ true
+ true
+ WIN32;_CRT_SECURE_NO_WARNINGS;NOMINMAX;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+ FreeImage.lib;cudart.lib;cublas.lib;%(AdditionalDependencies)
+
+
+ compute_35,sm_35
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+
+
+ Create
+ Create
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AnnotationTools/Filter2dAnnotations/Filter2dAnnotations.vcxproj.filters b/AnnotationTools/Filter2dAnnotations/Filter2dAnnotations.vcxproj.filters
new file mode 100644
index 0000000..d26326d
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/Filter2dAnnotations.vcxproj.filters
@@ -0,0 +1,75 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AnnotationTools/Filter2dAnnotations/GlobalDefines.h b/AnnotationTools/Filter2dAnnotations/GlobalDefines.h
new file mode 100644
index 0000000..7c8a2e4
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/GlobalDefines.h
@@ -0,0 +1,14 @@
+#ifndef GLOBAL_DEFINES_H
+#define GLOBAL_DEFINES_H
+
+
+#define MLIB_CUDA_SAFE_CALL(b) { if(b != cudaSuccess) throw MLIB_EXCEPTION(std::string(cudaGetErrorString(b)) + ":" + std::string(__FUNCTION__)); }
+#define MLIB_CUDA_SAFE_FREE(b) { if(!b) { MLIB_CUDA_SAFE_CALL(cudaFree(b)); b = NULL; } }
+#define MLIB_CUDA_CHECK_ERR(msg) { cudaError_t err = cudaGetLastError(); if (err != cudaSuccess) { throw MLIB_EXCEPTION(cudaGetErrorString( err )); } }
+
+
+
+
+#define MAX_NUM_LABELS_PER_SCENE 80 //current max = 76
+
+#endif //GLOBAL_DEFINES_H
\ No newline at end of file
diff --git a/AnnotationTools/Filter2dAnnotations/LabelUtil.h b/AnnotationTools/Filter2dAnnotations/LabelUtil.h
new file mode 100644
index 0000000..1f9d9c3
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/LabelUtil.h
@@ -0,0 +1,89 @@
+#pragma once
+
+class LabelUtil
+{
+public:
+ LabelUtil() {}
+ void init(const std::string& labelMapFile, const std::string& labelName = "category", const std::string& idName = "") {
+ if (!util::fileExists(labelMapFile)) throw MLIB_EXCEPTION(labelMapFile + " does not exist!");
+ m_maxLabel = 65535;//255;
+
+ getLabelMappingFromFile(labelMapFile, labelName, idName);
+
+ m_bIsInitialized = true;
+ }
+
+ static LabelUtil& getInstance() {
+ static LabelUtil s;
+ return s;
+ }
+ static LabelUtil& get() {
+ return getInstance();
+ }
+
+ bool getIdForLabel(const std::string& label, unsigned short& id) const {
+ const auto it = s_labelsToIds.find(label);
+ if (it == s_labelsToIds.end()) return false;
+ id = it->second;
+ return true;
+ }
+
+ bool getLabelForId(unsigned short id, std::string& label) const {
+ const auto it = s_idsToLabels.find(id);
+ if (it == s_idsToLabels.end()) return false;
+ label = it->second;
+ return true;
+ }
+
+private:
+
+ void getLabelMappingFromFile(const std::string& filename, const std::string& labelName, const std::string& idName)
+ {
+ if (!util::fileExists(filename)) throw MLIB_EXCEPTION("label mapping files does not exist!");
+ const char splitter = '\t';
+
+ s_labelsToIds.clear();
+ s_idsToLabels.clear();
+
+ std::ifstream s(filename); std::string line;
+ //read header
+ std::unordered_map header;
+ if (!std::getline(s, line)) throw MLIB_EXCEPTION("error reading label mapping file");
+ auto parts = util::split(line, splitter);
+ const unsigned int numElems = (unsigned int)parts.size();
+ for (unsigned int i = 0; i < parts.size(); i++) header[parts[i]] = i;
+
+ auto it = header.find(labelName);
+ if (it == header.end()) throw MLIB_EXCEPTION("could not find value " + labelName + " in label mapping file");
+ unsigned int labelIdx = it->second;
+ bool bUseExistingLabel = !idName.empty(); unsigned int idIdx = (unsigned int)-1;
+ if (bUseExistingLabel) {
+ it = header.find(idName);
+ if (it == header.end()) throw MLIB_EXCEPTION("could not find value " + idName + " in label mapping file");
+ idIdx = it->second;
+ }
+ //read elements
+ unsigned int lineCount = 1;
+ while (std::getline(s, line)) {
+ parts = util::split(line, splitter, true);
+ if (!parts[labelIdx].empty() && (!bUseExistingLabel || !parts[idIdx].empty())) {
+ unsigned int id = bUseExistingLabel ? util::convertTo(parts[idIdx]) : lineCount;
+ if (id > m_maxLabel) //skip
+ continue;
+ s_labelsToIds[parts[labelIdx]] = (unsigned short)id;
+ s_idsToLabels[(unsigned short)id] = parts[labelIdx];
+ }
+ ++lineCount;
+ }
+ s.close();
+
+ std::cout << "read " << s_labelsToIds.size() << " labels" << std::endl;
+ }
+
+ bool m_bIsInitialized;
+ unsigned short m_maxLabel;
+
+ std::unordered_map s_labelsToIds;
+ std::unordered_map s_idsToLabels;
+
+};
\ No newline at end of file
diff --git a/AnnotationTools/Filter2dAnnotations/MatrixConversion.h b/AnnotationTools/Filter2dAnnotations/MatrixConversion.h
new file mode 100644
index 0000000..bbf73ef
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/MatrixConversion.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "cuda_SimpleMatrixUtil.h"
+
+namespace MatrixConversion
+{
+ static mat4f toMlib(const float4x4& m) {
+ return mat4f(m.ptr());
+ }
+ static vec4f toMlib(const float4& v) {
+ return vec4f(v.x, v.y, v.z, v.w);
+ }
+ static vec3f toMlib(const float3& v) {
+ return vec3f(v.x, v.y, v.z);
+ }
+ static vec4i toMlib(const int4& v) {
+ return vec4i(v.x, v.y, v.z, v.w);
+ }
+ static vec3i toMlib(const int3& v) {
+ return vec3i(v.x, v.y, v.z);
+ }
+ static float4x4 toCUDA(const mat4f& m) {
+ return float4x4(m.getData());
+ }
+
+ static float4 toCUDA(const vec4f& v) {
+ return make_float4(v.x, v.y, v.z, v.w);
+ }
+ static float3 toCUDA(const vec3f& v) {
+ return make_float3(v.x, v.y, v.z);
+ }
+ static int4 toCUDA(const vec4i& v) {
+ return make_int4(v.x, v.y, v.z, v.w);
+ }
+ static int3 toCUDA(const vec3i& v) {
+ return make_int3(v.x, v.y, v.z);
+ }
+
+
+}
diff --git a/AnnotationTools/Filter2dAnnotations/cudaUtil.h b/AnnotationTools/Filter2dAnnotations/cudaUtil.h
new file mode 100644
index 0000000..9c5d4b8
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/cudaUtil.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#ifndef _CUDA_UTIL_
+#define _CUDA_UTIL_
+
+#undef max
+#undef min
+
+#include
+#include
+
+// Enable run time assertion checking in kernel code
+#define cudaAssert(condition) if (!(condition)) { printf("ASSERT: %s %s\n", #condition, __FILE__); }
+//#define cudaAssert(condition)
+
+#if defined(__CUDA_ARCH__)
+#define __CONDITIONAL_UNROLL__ #pragma unroll
+#else
+#define __CONDITIONAL_UNROLL__
+#endif
+
+#endif
diff --git a/AnnotationTools/Filter2dAnnotations/cuda_SimpleMatrixUtil.h b/AnnotationTools/Filter2dAnnotations/cuda_SimpleMatrixUtil.h
new file mode 100644
index 0000000..eeb6a4c
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/cuda_SimpleMatrixUtil.h
@@ -0,0 +1,1755 @@
+#pragma once
+
+#ifndef _CUDA_SIMPLE_MATRIX_UTIL_
+#define _CUDA_SIMPLE_MATRIX_UTIL_
+
+#define MINF __int_as_float(0xff800000)
+#define INF __int_as_float(0x7f800000)
+
+#include
+#include "cudaUtil.h"
+
+//////////////////////////////
+// float2x2
+//////////////////////////////
+
+class float2x2
+{
+public:
+
+ inline __device__ __host__ float2x2()
+ {
+ }
+
+ inline __device__ __host__ float2x2(const float values[4])
+ {
+ m11 = values[0]; m12 = values[1];
+ m21 = values[2]; m22 = values[3];
+ }
+
+ inline __device__ __host__ float2x2(const float2x2& other)
+ {
+ m11 = other.m11; m12 = other.m12;
+ m21 = other.m21; m22 = other.m22;
+ }
+
+ inline __device__ __host__ void setZero()
+ {
+ m11 = 0.0f; m12 = 0.0f;
+ m21 = 0.0f; m22 = 0.0f;
+ }
+
+ static inline __device__ __host__ float2x2 getIdentity()
+ {
+ float2x2 res;
+ res.setZero();
+ res.m11 = res.m22 = 1.0f;
+ return res;
+ }
+
+ inline __device__ __host__ float2x2& operator=(const float2x2 &other)
+ {
+ m11 = other.m11; m12 = other.m12;
+ m21 = other.m21; m22 = other.m22;
+ return *this;
+ }
+
+ inline __device__ __host__ float2x2 getInverse()
+ {
+ float2x2 res;
+ res.m11 = m22; res.m12 = -m12;
+ res.m21 = -m21; res.m22 = m11;
+
+ return res*(1.0f/det());
+ }
+
+ inline __device__ __host__ float det()
+ {
+ return m11*m22-m21*m12;
+ }
+
+ inline __device__ __host__ float2 operator*(const float2& v) const
+ {
+ return make_float2(m11*v.x + m12*v.y, m21*v.x + m22*v.y);
+ }
+
+ //! matrix scalar multiplication
+ inline __device__ __host__ float2x2 operator*(const float t) const
+ {
+ float2x2 res;
+ res.m11 = m11 * t; res.m12 = m12 * t;
+ res.m21 = m21 * t; res.m22 = m22 * t;
+ return res;
+ }
+
+ //! matrix matrix multiplication
+ inline __device__ __host__ float2x2 operator*(const float2x2& other) const
+ {
+ float2x2 res;
+ res.m11 = m11 * other.m11 + m12 * other.m21;
+ res.m12 = m11 * other.m12 + m12 * other.m22;
+ res.m21 = m21 * other.m11 + m22 * other.m21;
+ res.m22 = m21 * other.m12 + m22 * other.m22;
+ return res;
+ }
+
+ //! matrix matrix addition
+ inline __device__ __host__ float2x2 operator+(const float2x2& other) const
+ {
+ float2x2 res;
+ res.m11 = m11 + other.m11;
+ res.m12 = m12 + other.m12;
+ res.m21 = m21 + other.m21;
+ res.m22 = m22 + other.m22;
+ return res;
+ }
+
+ inline __device__ __host__ float& operator()(int i, int j)
+ {
+ return entries2[i][j];
+ }
+
+ inline __device__ __host__ float operator()(int i, int j) const
+ {
+ return entries2[i][j];
+ }
+
+ inline __device__ __host__ const float* ptr() const {
+ return entries;
+ }
+ inline __device__ __host__ float* ptr() {
+ return entries;
+ }
+
+ union
+ {
+ struct
+ {
+ float m11; float m12;
+ float m21; float m22;
+ };
+
+ float entries[4];
+ float entries2[2][2];
+ };
+};
+
+//////////////////////////////
+// float2x3
+//////////////////////////////
+
+class float2x3
+{
+public:
+
+ inline __device__ __host__ float2x3()
+ {
+ }
+
+ inline __device__ __host__ float2x3(const float values[6])
+ {
+ m11 = values[0]; m12 = values[1]; m13 = values[2];
+ m21 = values[3]; m22 = values[4]; m23 = values[5];
+ }
+
+ inline __device__ __host__ float2x3(const float2x3& other)
+ {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23;
+ }
+
+ inline __device__ __host__ float2x3& operator=(const float2x3 &other)
+ {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23;
+ return *this;
+ }
+
+ inline __device__ __host__ float2 operator*(const float3 &v) const
+ {
+ return make_float2(m11*v.x + m12*v.y + m13*v.z, m21*v.x + m22*v.y + m23*v.z);
+ }
+
+ //! matrix scalar multiplication
+ inline __device__ __host__ float2x3 operator*(const float t) const
+ {
+ float2x3 res;
+ res.m11 = m11 * t; res.m12 = m12 * t; res.m13 = m13 * t;
+ res.m21 = m21 * t; res.m22 = m22 * t; res.m23 = m23 * t;
+ return res;
+ }
+
+ //! matrix scalar division
+ inline __device__ __host__ float2x3 operator/(const float t) const
+ {
+ float2x3 res;
+ res.m11 = m11 / t; res.m12 = m12 / t; res.m13 = m13 / t;
+ res.m21 = m21 / t; res.m22 = m22 / t; res.m23 = m23 / t;
+ return res;
+ }
+
+ inline __device__ __host__ float& operator()(int i, int j)
+ {
+ return entries2[i][j];
+ }
+
+ inline __device__ __host__ float operator()(int i, int j) const
+ {
+ return entries2[i][j];
+ }
+
+ inline __device__ __host__ const float* ptr() const {
+ return entries;
+ }
+ inline __device__ __host__ float* ptr() {
+ return entries;
+ }
+
+ union
+ {
+ struct
+ {
+ float m11; float m12; float m13;
+ float m21; float m22; float m23;
+ };
+
+ float entries[6];
+ float entries2[3][2];
+ };
+};
+
+//////////////////////////////
+// float3x2
+//////////////////////////////
+
+class float3x2
+{
+public:
+
+ inline __device__ __host__ float3x2()
+ {
+ }
+
+ inline __device__ __host__ float3x2(const float values[6])
+ {
+ m11 = values[0]; m12 = values[1];
+ m21 = values[2]; m22 = values[3];
+ m31 = values[4]; m32 = values[5];
+ }
+
+ inline __device__ __host__ float3x2& operator=(const float3x2& other)
+ {
+ m11 = other.m11; m12 = other.m12;
+ m21 = other.m21; m22 = other.m22;
+ m31 = other.m31; m32 = other.m32;
+ return *this;
+ }
+
+ inline __device__ __host__ float3 operator*(const float2& v) const
+ {
+ return make_float3(m11*v.x + m12*v.y, m21*v.x + m22*v.y, m31*v.x + m32*v.y);
+ }
+
+ inline __device__ __host__ float3x2 operator*(const float t) const
+ {
+ float3x2 res;
+ res.m11 = m11 * t; res.m12 = m12 * t;
+ res.m21 = m21 * t; res.m22 = m22 * t;
+ res.m31 = m31 * t; res.m32 = m32 * t;
+ return res;
+ }
+
+ inline __device__ __host__ float& operator()(int i, int j)
+ {
+ return entries2[i][j];
+ }
+
+ inline __device__ __host__ float operator()(int i, int j) const
+ {
+ return entries2[i][j];
+ }
+
+ inline __device__ __host__ float2x3 getTranspose()
+ {
+ float2x3 res;
+ res.m11 = m11; res.m12 = m21; res.m13 = m31;
+ res.m21 = m12; res.m22 = m22; res.m23 = m32;
+ return res;
+ }
+
+ inline __device__ __host__ const float* ptr() const {
+ return entries;
+ }
+ inline __device__ __host__ float* ptr() {
+ return entries;
+ }
+
+ union
+ {
+ struct
+ {
+ float m11; float m12;
+ float m21; float m22;
+ float m31; float m32;
+ };
+
+ float entries[6];
+ float entries2[3][2];
+ };
+};
+
+inline __device__ __host__ float2x2 matMul(const float2x3& m0, const float3x2& m1)
+{
+ float2x2 res;
+ res.m11 = m0.m11*m1.m11+m0.m12*m1.m21+m0.m13*m1.m31;
+ res.m12 = m0.m11*m1.m12+m0.m12*m1.m22+m0.m13*m1.m32;
+ res.m21 = m0.m21*m1.m11+m0.m22*m1.m21+m0.m23*m1.m31;
+ res.m22 = m0.m21*m1.m12+m0.m22*m1.m22+m0.m23*m1.m32;
+ return res;
+}
+
+class float3x3 {
+public:
+ inline __device__ __host__ float3x3() {
+
+ }
+ inline __device__ __host__ float3x3(const float values[9]) {
+ m11 = values[0]; m12 = values[1]; m13 = values[2];
+ m21 = values[3]; m22 = values[4]; m23 = values[5];
+ m31 = values[6]; m32 = values[7]; m33 = values[8];
+ }
+
+ inline __device__ __host__ float3x3(const float3x3& other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33;
+ }
+
+ explicit inline __device__ __host__ float3x3(const float2x2& other) {
+ m11 = other.m11; m12 = other.m12; m13 = 0.0;
+ m21 = other.m21; m22 = other.m22; m23 = 0.0;
+ m31 = 0.0; m32 = 0.0; m33 = 0.0;
+ }
+
+ inline __device__ __host__ float3x3& operator=(const float3x3 &other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33;
+ return *this;
+ }
+
+ inline __device__ __host__ float& operator()(int i, int j) {
+ return entries2[i][j];
+ }
+
+ inline __device__ __host__ float operator()(int i, int j) const {
+ return entries2[i][j];
+ }
+
+
+ static inline __device__ __host__ void swap(float& v0, float& v1) {
+ float tmp = v0;
+ v0 = v1;
+ v1 = tmp;
+ }
+
+ inline __device__ __host__ void transpose() {
+ swap(m12, m21);
+ swap(m13, m31);
+ swap(m23, m32);
+ }
+ inline __device__ __host__ float3x3 getTranspose() const {
+ float3x3 ret = *this;
+ ret.transpose();
+ return ret;
+ }
+
+ //! inverts the matrix
+ inline __device__ __host__ void invert() {
+ *this = getInverse();
+ }
+
+ //! computes the inverse of the matrix; the result is returned
+ inline __device__ __host__ float3x3 getInverse() const {
+ float3x3 res;
+ res.entries[0] = entries[4]*entries[8] - entries[5]*entries[7];
+ res.entries[1] = -entries[1]*entries[8] + entries[2]*entries[7];
+ res.entries[2] = entries[1]*entries[5] - entries[2]*entries[4];
+
+ res.entries[3] = -entries[3]*entries[8] + entries[5]*entries[6];
+ res.entries[4] = entries[0]*entries[8] - entries[2]*entries[6];
+ res.entries[5] = -entries[0]*entries[5] + entries[2]*entries[3];
+
+ res.entries[6] = entries[3]*entries[7] - entries[4]*entries[6];
+ res.entries[7] = -entries[0]*entries[7] + entries[1]*entries[6];
+ res.entries[8] = entries[0]*entries[4] - entries[1]*entries[3];
+ float nom = 1.0f/det();
+ return res * nom;
+ }
+
+ inline __device__ __host__ void setZero(float value = 0.0f) {
+ m11 = m12 = m13 = value;
+ m21 = m22 = m23 = value;
+ m31 = m32 = m33 = value;
+ }
+
+ inline __device__ __host__ float det() const {
+ return
+ + m11*m22*m33
+ + m12*m23*m31
+ + m13*m21*m32
+ - m31*m22*m13
+ - m32*m23*m11
+ - m33*m21*m12;
+ }
+
+ inline __device__ __host__ float3 getRow(unsigned int i) {
+ return make_float3(entries[3*i+0], entries[3*i+1], entries[3*i+2]);
+ }
+
+ inline __device__ __host__ void setRow(unsigned int i, float3& r) {
+ entries[3*i+0] = r.x;
+ entries[3*i+1] = r.y;
+ entries[3*i+2] = r.z;
+ }
+
+ inline __device__ __host__ void normalizeRows()
+ {
+ //#pragma unroll 3
+ for(unsigned int i = 0; i<3; i++)
+ {
+ float3 r = getRow(i);
+ r/=length(r);
+ setRow(i, r);
+ }
+ }
+
+ //! computes the product of two matrices (result stored in this)
+ inline __device__ __host__ void mult(const float3x3 &other) {
+ float3x3 res;
+ res.m11 = m11 * other.m11 + m12 * other.m21 + m13 * other.m31;
+ res.m12 = m11 * other.m12 + m12 * other.m22 + m13 * other.m32;
+ res.m13 = m11 * other.m13 + m12 * other.m23 + m13 * other.m33;
+
+ res.m21 = m21 * other.m11 + m22 * other.m21 + m23 * other.m31;
+ res.m22 = m21 * other.m12 + m22 * other.m22 + m23 * other.m32;
+ res.m23 = m21 * other.m13 + m22 * other.m23 + m23 * other.m33;
+
+ res.m31 = m21 * other.m11 + m32 * other.m21 + m33 * other.m31;
+ res.m32 = m21 * other.m12 + m32 * other.m22 + m33 * other.m32;
+ res.m33 = m21 * other.m13 + m32 * other.m23 + m33 * other.m33;
+ *this = res;
+ }
+
+ //! computes the sum of two matrices (result stored in this)
+ inline __device__ __host__ void add(const float3x3 &other) {
+ m11 += other.m11; m12 += other.m12; m13 += other.m13;
+ m21 += other.m21; m22 += other.m22; m23 += other.m23;
+ m31 += other.m31; m32 += other.m32; m33 += other.m33;
+ }
+
+ //! standard matrix matrix multiplication
+ inline __device__ __host__ float3x3 operator*(const float3x3 &other) const {
+ float3x3 res;
+ res.m11 = m11 * other.m11 + m12 * other.m21 + m13 * other.m31;
+ res.m12 = m11 * other.m12 + m12 * other.m22 + m13 * other.m32;
+ res.m13 = m11 * other.m13 + m12 * other.m23 + m13 * other.m33;
+
+ res.m21 = m21 * other.m11 + m22 * other.m21 + m23 * other.m31;
+ res.m22 = m21 * other.m12 + m22 * other.m22 + m23 * other.m32;
+ res.m23 = m21 * other.m13 + m22 * other.m23 + m23 * other.m33;
+
+ res.m31 = m31 * other.m11 + m32 * other.m21 + m33 * other.m31;
+ res.m32 = m31 * other.m12 + m32 * other.m22 + m33 * other.m32;
+ res.m33 = m31 * other.m13 + m32 * other.m23 + m33 * other.m33;
+ return res;
+ }
+
+ //! standard matrix matrix multiplication
+ inline __device__ __host__ float3x2 operator*(const float3x2 &other) const {
+ float3x2 res;
+ res.m11 = m11 * other.m11 + m12 * other.m21 + m13 * other.m31;
+ res.m12 = m11 * other.m12 + m12 * other.m22 + m13 * other.m32;
+
+ res.m21 = m21 * other.m11 + m22 * other.m21 + m23 * other.m31;
+ res.m22 = m21 * other.m12 + m22 * other.m22 + m23 * other.m32;
+
+ res.m31 = m31 * other.m11 + m32 * other.m21 + m33 * other.m31;
+ res.m32 = m31 * other.m12 + m32 * other.m22 + m33 * other.m32;
+ return res;
+ }
+
+ inline __device__ __host__ float3 operator*(const float3 &v) const {
+ return make_float3(
+ m11*v.x + m12*v.y + m13*v.z,
+ m21*v.x + m22*v.y + m23*v.z,
+ m31*v.x + m32*v.y + m33*v.z
+ );
+ }
+
+ inline __device__ __host__ float3x3 operator*(const float t) const {
+ float3x3 res;
+ res.m11 = m11 * t; res.m12 = m12 * t; res.m13 = m13 * t;
+ res.m21 = m21 * t; res.m22 = m22 * t; res.m23 = m23 * t;
+ res.m31 = m31 * t; res.m32 = m32 * t; res.m33 = m33 * t;
+ return res;
+ }
+
+
+ inline __device__ __host__ float3x3 operator+(const float3x3 &other) const {
+ float3x3 res;
+ res.m11 = m11 + other.m11; res.m12 = m12 + other.m12; res.m13 = m13 + other.m13;
+ res.m21 = m21 + other.m21; res.m22 = m22 + other.m22; res.m23 = m23 + other.m23;
+ res.m31 = m31 + other.m31; res.m32 = m32 + other.m32; res.m33 = m33 + other.m33;
+ return res;
+ }
+
+ inline __device__ __host__ float3x3 operator-(const float3x3 &other) const {
+ float3x3 res;
+ res.m11 = m11 - other.m11; res.m12 = m12 - other.m12; res.m13 = m13 - other.m13;
+ res.m21 = m21 - other.m21; res.m22 = m22 - other.m22; res.m23 = m23 - other.m23;
+ res.m31 = m31 - other.m31; res.m32 = m32 - other.m32; res.m33 = m33 - other.m33;
+ return res;
+ }
+
+ static inline __device__ __host__ float3x3 getIdentity() {
+ float3x3 res;
+ res.setZero();
+ res.m11 = res.m22 = res.m33 = 1.0f;
+ return res;
+ }
+
+ static inline __device__ __host__ float3x3 getZeroMatrix() {
+ float3x3 res;
+ res.setZero();
+ return res;
+ }
+
+ static inline __device__ __host__ float3x3 getDiagonalMatrix(float diag = 1.0f) {
+ float3x3 res;
+ res.m11 = diag; res.m12 = 0.0f; res.m13 = 0.0f;
+ res.m21 = 0.0f; res.m22 = diag; res.m23 = 0.0f;
+ res.m31 = 0.0f; res.m32 = 0.0f; res.m33 = diag;
+ return res;
+ }
+
+ static inline __device__ __host__ float3x3 tensorProduct(const float3 &v, const float3 &vt) {
+ float3x3 res;
+ res.m11 = v.x * vt.x; res.m12 = v.x * vt.y; res.m13 = v.x * vt.z;
+ res.m21 = v.y * vt.x; res.m22 = v.y * vt.y; res.m23 = v.y * vt.z;
+ res.m31 = v.z * vt.x; res.m32 = v.z * vt.y; res.m33 = v.z * vt.z;
+ return res;
+ }
+
+ inline __device__ __host__ const float* ptr() const {
+ return entries;
+ }
+ inline __device__ __host__ float* ptr() {
+ return entries;
+ }
+
+ union {
+ struct {
+ float m11; float m12; float m13;
+ float m21; float m22; float m23;
+ float m31; float m32; float m33;
+ };
+ float entries[9];
+ float entries2[3][3];
+ };
+};
+
+
+inline __device__ __host__ float2x3 matMul(const float2x3& m0, const float3x3& m1)
+{
+ float2x3 res;
+ res.m11 = m0.m11*m1.m11+m0.m12*m1.m21+m0.m13*m1.m31;
+ res.m12 = m0.m11*m1.m12+m0.m12*m1.m22+m0.m13*m1.m32;
+ res.m13 = m0.m11*m1.m13+m0.m12*m1.m23+m0.m13*m1.m33;
+
+ res.m21 = m0.m21*m1.m11+m0.m22*m1.m21+m0.m23*m1.m31;
+ res.m22 = m0.m21*m1.m12+m0.m22*m1.m22+m0.m23*m1.m32;
+ res.m23 = m0.m21*m1.m13+m0.m22*m1.m23+m0.m23*m1.m33;
+ return res;
+}
+
+// (1x2) row matrix as float2
+inline __device__ __host__ float3 matMul(const float2& m0, const float2x3& m1)
+{
+ float3 res;
+ res.x = m0.x*m1.m11+m0.y*m1.m21;
+ res.y = m0.x*m1.m12+m0.y*m1.m22;
+ res.z = m0.x*m1.m13+m0.y*m1.m23;
+
+ return res;
+}
+
+
+class float3x4 {
+public:
+ inline __device__ __host__ float3x4() {
+
+ }
+ inline __device__ __host__ float3x4(const float values[12]) {
+ m11 = values[0]; m12 = values[1]; m13 = values[2]; m14 = values[3];
+ m21 = values[4]; m22 = values[5]; m23 = values[6]; m24 = values[7];
+ m31 = values[8]; m32 = values[9]; m33 = values[10]; m34 = values[11];
+ }
+
+ inline __device__ __host__ float3x4(const float3x4& other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13; m14 = other.m14;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23; m24 = other.m24;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33; m34 = other.m34;
+ }
+
+ inline __device__ __host__ float3x4(const float3x3& other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13; m14 = 0.0f;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23; m24 = 0.0f;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33; m34 = 0.0f;
+ }
+
+ inline __device__ __host__ float3x4 operator=(const float3x4 &other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13; m14 = other.m14;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23; m24 = other.m24;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33; m34 = other.m34;
+ return *this;
+ }
+
+ inline __device__ __host__ float3x4& operator=(const float3x3 &other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13; m14 = 0.0f;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23; m24 = 0.0f;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33; m34 = 0.0f;
+ return *this;
+ }
+
+ //! assumes the last line of the matrix implicitly to be (0,0,0,1)
+ inline __device__ __host__ float4 operator*(const float4 &v) const {
+ return make_float4(
+ m11*v.x + m12*v.y + m13*v.z + m14*v.w,
+ m21*v.x + m22*v.y + m23*v.z + m24*v.w,
+ m31*v.x + m32*v.y + m33*v.z + m34*v.w,
+ v.w
+ );
+ }
+
+ //! assumes an implicit 1 in w component of the input vector
+ inline __device__ __host__ float3 operator*(const float3 &v) const {
+ return make_float3(
+ m11*v.x + m12*v.y + m13*v.z + m14,
+ m21*v.x + m22*v.y + m23*v.z + m24,
+ m31*v.x + m32*v.y + m33*v.z + m34
+ );
+ }
+
+ //! matrix scalar multiplication
+ inline __device__ __host__ float3x4 operator*(const float t) const {
+ float3x4 res;
+ res.m11 = m11 * t; res.m12 = m12 * t; res.m13 = m13 * t; res.m14 = m14 * t;
+ res.m21 = m21 * t; res.m22 = m22 * t; res.m23 = m23 * t; res.m24 = m24 * t;
+ res.m31 = m31 * t; res.m32 = m32 * t; res.m33 = m33 * t; res.m34 = m34 * t;
+ return res;
+ }
+ inline __device__ __host__ float3x4& operator*=(const float t) {
+ *this = *this * t;
+ return *this;
+ }
+
+ //! matrix scalar division
+ inline __device__ __host__ float3x4 operator/(const float t) const {
+ float3x4 res;
+ res.m11 = m11 / t; res.m12 = m12 / t; res.m13 = m13 / t; res.m14 = m14 / t;
+ res.m21 = m21 / t; res.m22 = m22 / t; res.m23 = m23 / t; res.m24 = m24 / t;
+ res.m31 = m31 / t; res.m32 = m32 / t; res.m33 = m33 / t; res.m34 = m34 / t;
+ return res;
+ }
+ inline __device__ __host__ float3x4& operator/=(const float t) {
+ *this = *this / t;
+ return *this;
+ }
+
+ //! assumes the last line of the matrix implicitly to be (0,0,0,1)
+ inline __device__ __host__ float3x4 operator*(const float3x4 &other) const {
+ float3x4 res;
+ res.m11 = m11*other.m11 + m12*other.m21 + m13*other.m31;
+ res.m12 = m11*other.m12 + m12*other.m22 + m13*other.m32;
+ res.m13 = m11*other.m13 + m12*other.m23 + m13*other.m33;
+ res.m14 = m11*other.m14 + m12*other.m24 + m13*other.m34 + m14;
+
+ res.m21 = m21*other.m11 + m22*other.m21 + m23*other.m31;
+ res.m22 = m21*other.m12 + m22*other.m22 + m23*other.m32;
+ res.m23 = m21*other.m13 + m22*other.m23 + m23*other.m33;
+ res.m24 = m21*other.m14 + m22*other.m24 + m23*other.m34 + m24;
+
+ res.m31 = m31*other.m11 + m32*other.m21 + m33*other.m31;
+ res.m32 = m31*other.m12 + m32*other.m22 + m33*other.m32;
+ res.m33 = m31*other.m13 + m32*other.m23 + m33*other.m33;
+ res.m34 = m31*other.m14 + m32*other.m24 + m33*other.m34 + m34;
+
+ //res.m41 = m41*other.m11 + m42*other.m21 + m43*other.m31 + m44*other.m41;
+ //res.m42 = m41*other.m12 + m42*other.m22 + m43*other.m32 + m44*other.m42;
+ //res.m43 = m41*other.m13 + m42*other.m23 + m43*other.m33 + m44*other.m43;
+ //res.m44 = m41*other.m14 + m42*other.m24 + m43*other.m34 + m44*other.m44;
+
+ return res;
+ }
+
+ //! assumes the last line of the matrix implicitly to be (0,0,0,1); and a (0,0,0) translation of other
+ inline __device__ __host__ float3x4 operator*(const float3x3 &other) const {
+ float3x4 res;
+ res.m11 = m11*other.m11 + m12*other.m21 + m13*other.m31;
+ res.m12 = m11*other.m12 + m12*other.m22 + m13*other.m32;
+ res.m13 = m11*other.m13 + m12*other.m23 + m13*other.m33;
+ res.m14 = m14;
+
+ res.m21 = m21*other.m11 + m22*other.m21 + m23*other.m31;
+ res.m22 = m21*other.m12 + m22*other.m22 + m23*other.m32;
+ res.m23 = m21*other.m13 + m22*other.m23 + m23*other.m33;
+ res.m24 = m24;
+
+ res.m31 = m31*other.m11 + m32*other.m21 + m33*other.m31;
+ res.m32 = m31*other.m12 + m32*other.m22 + m33*other.m32;
+ res.m33 = m31*other.m13 + m32*other.m23 + m33*other.m33;
+ res.m34 = m34;
+
+ return res;
+ }
+
+
+
+ inline __device__ __host__ float& operator()(int i, int j) {
+ return entries2[i][j];
+ }
+
+ inline __device__ __host__ float operator()(int i, int j) const {
+ return entries2[i][j];
+ }
+
+ //! returns the translation part of the matrix
+ inline __device__ __host__ float3 getTranslation() {
+ return make_float3(m14, m24, m34);
+ }
+
+ //! sets only the translation part of the matrix (other values remain unchanged)
+ inline __device__ __host__ void setTranslation(const float3 &t) {
+ m14 = t.x;
+ m24 = t.y;
+ m34 = t.z;
+ }
+
+ //! returns the 3x3 part of the matrix
+ inline __device__ __host__ float3x3 getFloat3x3() {
+ float3x3 ret;
+ ret.m11 = m11; ret.m12 = m12; ret.m13 = m13;
+ ret.m21 = m21; ret.m22 = m22; ret.m23 = m23;
+ ret.m31 = m31; ret.m32 = m32; ret.m33 = m33;
+ return ret;
+ }
+
+ //! sets the 3x3 part of the matrix (other values remain unchanged)
+ inline __device__ __host__ void setFloat3x3(const float3x3 &other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33;
+ }
+
+ //! inverts the matrix
+ inline __device__ __host__ void inverse() {
+ *this = getInverse();
+ }
+
+ //! computes the inverse of the matrix
+ inline __device__ __host__ float3x4 getInverse() {
+ float3x3 A = getFloat3x3();
+ A.invert();
+ float3 t = getTranslation();
+ t = A*t;
+
+ float3x4 ret;
+ ret.setFloat3x3(A);
+ ret.setTranslation(make_float3(-t.x, -t.y, -t.z)); //float3 doesn't have unary '-'... thank you cuda
+ return ret;
+ }
+
+ //! prints the matrix; only host
+ __host__ void print() {
+ std::cout <<
+ m11 << " " << m12 << " " << m13 << " " << m14 << std::endl <<
+ m21 << " " << m22 << " " << m23 << " " << m24 << std::endl <<
+ m31 << " " << m32 << " " << m33 << " " << m34 << std::endl <<
+ std::endl;
+ }
+
+ inline __device__ __host__ const float* ptr() const {
+ return entries;
+ }
+ inline __device__ __host__ float* ptr() {
+ return entries;
+ }
+
+ union {
+ struct {
+ float m11; float m12; float m13; float m14;
+ float m21; float m22; float m23; float m24;
+ float m31; float m32; float m33; float m34;
+ };
+ float entries[9];
+ float entries2[3][4];
+ };
+};
+
+
+
+class float4x4 {
+public:
+ inline __device__ __host__ float4x4() {
+
+ }
+ inline __device__ __host__ float4x4(const float values[16]) {
+ m11 = values[0]; m12 = values[1]; m13 = values[2]; m14 = values[3];
+ m21 = values[4]; m22 = values[5]; m23 = values[6]; m24 = values[7];
+ m31 = values[8]; m32 = values[9]; m33 = values[10]; m34 = values[11];
+ m41 = values[12]; m42 = values[13]; m43 = values[14]; m44 = values[15];
+ }
+
+ inline __device__ __host__ float4x4(const float4x4& other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13; m14 = other.m14;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23; m24 = other.m24;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33; m34 = other.m34;
+ m41 = other.m41; m42 = other.m42; m43 = other.m43; m44 = other.m44;
+ }
+
+ //implicitly assumes last line to (0,0,0,1)
+ inline __device__ __host__ float4x4(const float3x4& other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13; m14 = other.m14;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23; m24 = other.m24;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33; m34 = other.m34;
+ m41 = 0.0f; m42 = 0.0f; m43 = 0.0f; m44 = 1.0f;
+ }
+
+ inline __device__ __host__ float4x4(const float3x3& other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13; m14 = 0.0f;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23; m24 = 0.0f;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33; m34 = 0.0f;
+ m41 = 0.0f; m42 = 0.0f; m43 = 0.0f; m44 = 1.0f;
+ }
+
+ inline __device__ __host__ float4x4 operator=(const float4x4 &other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13; m14 = other.m14;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23; m24 = other.m24;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33; m34 = other.m34;
+ m41 = other.m41; m42 = other.m42; m43 = other.m43; m44 = other.m44;
+ return *this;
+ }
+
+ inline __device__ __host__ float4x4 operator=(const float3x4 &other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13; m14 = other.m14;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23; m24 = other.m24;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33; m34 = other.m34;
+ m41 = 0.0f; m42 = 0.0f; m43 = 0.0f; m44 = 1.0f;
+ return *this;
+ }
+
+ inline __device__ __host__ float4x4& operator=(const float3x3 &other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13; m14 = 0.0f;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23; m24 = 0.0f;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33; m34 = 0.0f;
+ m41 = 0.0f; m42 = 0.0f; m43 = 0.0f; m44 = 1.0f;
+ return *this;
+ }
+
+
+ //! not tested
+ inline __device__ __host__ float4x4 operator*(const float4x4 &other) const {
+ float4x4 res;
+ res.m11 = m11*other.m11 + m12*other.m21 + m13*other.m31 + m14*other.m41;
+ res.m12 = m11*other.m12 + m12*other.m22 + m13*other.m32 + m14*other.m42;
+ res.m13 = m11*other.m13 + m12*other.m23 + m13*other.m33 + m14*other.m43;
+ res.m14 = m11*other.m14 + m12*other.m24 + m13*other.m34 + m14*other.m44;
+
+ res.m21 = m21*other.m11 + m22*other.m21 + m23*other.m31 + m24*other.m41;
+ res.m22 = m21*other.m12 + m22*other.m22 + m23*other.m32 + m24*other.m42;
+ res.m23 = m21*other.m13 + m22*other.m23 + m23*other.m33 + m24*other.m43;
+ res.m24 = m21*other.m14 + m22*other.m24 + m23*other.m34 + m24*other.m44;
+
+ res.m31 = m31*other.m11 + m32*other.m21 + m33*other.m31 + m34*other.m41;
+ res.m32 = m31*other.m12 + m32*other.m22 + m33*other.m32 + m34*other.m42;
+ res.m33 = m31*other.m13 + m32*other.m23 + m33*other.m33 + m34*other.m43;
+ res.m34 = m31*other.m14 + m32*other.m24 + m33*other.m34 + m34*other.m44;
+
+ res.m41 = m41*other.m11 + m42*other.m21 + m43*other.m31 + m44*other.m41;
+ res.m42 = m41*other.m12 + m42*other.m22 + m43*other.m32 + m44*other.m42;
+ res.m43 = m41*other.m13 + m42*other.m23 + m43*other.m33 + m44*other.m43;
+ res.m44 = m41*other.m14 + m42*other.m24 + m43*other.m34 + m44*other.m44;
+
+ return res;
+ }
+
+ // untested
+ inline __device__ __host__ float4 operator*(const float4& v) const
+ {
+ return make_float4(
+ m11*v.x + m12*v.y + m13*v.z + m14*v.w,
+ m21*v.x + m22*v.y + m23*v.z + m24*v.w,
+ m31*v.x + m32*v.y + m33*v.z + m34*v.w,
+ m41*v.x + m42*v.y + m43*v.z + m44*v.w
+ );
+ }
+
+ // untested
+ //implicitly assumes w to be 1
+ inline __device__ __host__ float3 operator*(const float3& v) const
+ {
+ return make_float3(
+ m11*v.x + m12*v.y + m13*v.z + m14*1.0f,
+ m21*v.x + m22*v.y + m23*v.z + m24*1.0f,
+ m31*v.x + m32*v.y + m33*v.z + m34*1.0f
+ );
+ }
+
+ inline __device__ __host__ float& operator()(int i, int j) {
+ return entries2[i][j];
+ }
+
+ inline __device__ __host__ float operator()(int i, int j) const {
+ return entries2[i][j];
+ }
+
+
+ static inline __device__ __host__ void swap(float& v0, float& v1) {
+ float tmp = v0;
+ v0 = v1;
+ v1 = tmp;
+ }
+
+ inline __device__ __host__ void transpose() {
+ swap(m12, m21);
+ swap(m13, m31);
+ swap(m23, m32);
+ swap(m41, m14);
+ swap(m42, m24);
+ swap(m43, m34);
+ }
+ inline __device__ __host__ float4x4 getTranspose() const {
+ float4x4 ret = *this;
+ ret.transpose();
+ return ret;
+ }
+
+
+ inline __device__ __host__ void invert() {
+ *this = getInverse();
+ }
+
+ //! return the inverse matrix; but does not change the current matrix
+ inline __device__ __host__ float4x4 getInverse() const {
+ float inv[16];
+
+ inv[0] = entries[5] * entries[10] * entries[15] -
+ entries[5] * entries[11] * entries[14] -
+ entries[9] * entries[6] * entries[15] +
+ entries[9] * entries[7] * entries[14] +
+ entries[13] * entries[6] * entries[11] -
+ entries[13] * entries[7] * entries[10];
+
+ inv[4] = -entries[4] * entries[10] * entries[15] +
+ entries[4] * entries[11] * entries[14] +
+ entries[8] * entries[6] * entries[15] -
+ entries[8] * entries[7] * entries[14] -
+ entries[12] * entries[6] * entries[11] +
+ entries[12] * entries[7] * entries[10];
+
+ inv[8] = entries[4] * entries[9] * entries[15] -
+ entries[4] * entries[11] * entries[13] -
+ entries[8] * entries[5] * entries[15] +
+ entries[8] * entries[7] * entries[13] +
+ entries[12] * entries[5] * entries[11] -
+ entries[12] * entries[7] * entries[9];
+
+ inv[12] = -entries[4] * entries[9] * entries[14] +
+ entries[4] * entries[10] * entries[13] +
+ entries[8] * entries[5] * entries[14] -
+ entries[8] * entries[6] * entries[13] -
+ entries[12] * entries[5] * entries[10] +
+ entries[12] * entries[6] * entries[9];
+
+ inv[1] = -entries[1] * entries[10] * entries[15] +
+ entries[1] * entries[11] * entries[14] +
+ entries[9] * entries[2] * entries[15] -
+ entries[9] * entries[3] * entries[14] -
+ entries[13] * entries[2] * entries[11] +
+ entries[13] * entries[3] * entries[10];
+
+ inv[5] = entries[0] * entries[10] * entries[15] -
+ entries[0] * entries[11] * entries[14] -
+ entries[8] * entries[2] * entries[15] +
+ entries[8] * entries[3] * entries[14] +
+ entries[12] * entries[2] * entries[11] -
+ entries[12] * entries[3] * entries[10];
+
+ inv[9] = -entries[0] * entries[9] * entries[15] +
+ entries[0] * entries[11] * entries[13] +
+ entries[8] * entries[1] * entries[15] -
+ entries[8] * entries[3] * entries[13] -
+ entries[12] * entries[1] * entries[11] +
+ entries[12] * entries[3] * entries[9];
+
+ inv[13] = entries[0] * entries[9] * entries[14] -
+ entries[0] * entries[10] * entries[13] -
+ entries[8] * entries[1] * entries[14] +
+ entries[8] * entries[2] * entries[13] +
+ entries[12] * entries[1] * entries[10] -
+ entries[12] * entries[2] * entries[9];
+
+ inv[2] = entries[1] * entries[6] * entries[15] -
+ entries[1] * entries[7] * entries[14] -
+ entries[5] * entries[2] * entries[15] +
+ entries[5] * entries[3] * entries[14] +
+ entries[13] * entries[2] * entries[7] -
+ entries[13] * entries[3] * entries[6];
+
+ inv[6] = -entries[0] * entries[6] * entries[15] +
+ entries[0] * entries[7] * entries[14] +
+ entries[4] * entries[2] * entries[15] -
+ entries[4] * entries[3] * entries[14] -
+ entries[12] * entries[2] * entries[7] +
+ entries[12] * entries[3] * entries[6];
+
+ inv[10] = entries[0] * entries[5] * entries[15] -
+ entries[0] * entries[7] * entries[13] -
+ entries[4] * entries[1] * entries[15] +
+ entries[4] * entries[3] * entries[13] +
+ entries[12] * entries[1] * entries[7] -
+ entries[12] * entries[3] * entries[5];
+
+ inv[14] = -entries[0] * entries[5] * entries[14] +
+ entries[0] * entries[6] * entries[13] +
+ entries[4] * entries[1] * entries[14] -
+ entries[4] * entries[2] * entries[13] -
+ entries[12] * entries[1] * entries[6] +
+ entries[12] * entries[2] * entries[5];
+
+ inv[3] = -entries[1] * entries[6] * entries[11] +
+ entries[1] * entries[7] * entries[10] +
+ entries[5] * entries[2] * entries[11] -
+ entries[5] * entries[3] * entries[10] -
+ entries[9] * entries[2] * entries[7] +
+ entries[9] * entries[3] * entries[6];
+
+ inv[7] = entries[0] * entries[6] * entries[11] -
+ entries[0] * entries[7] * entries[10] -
+ entries[4] * entries[2] * entries[11] +
+ entries[4] * entries[3] * entries[10] +
+ entries[8] * entries[2] * entries[7] -
+ entries[8] * entries[3] * entries[6];
+
+ inv[11] = -entries[0] * entries[5] * entries[11] +
+ entries[0] * entries[7] * entries[9] +
+ entries[4] * entries[1] * entries[11] -
+ entries[4] * entries[3] * entries[9] -
+ entries[8] * entries[1] * entries[7] +
+ entries[8] * entries[3] * entries[5];
+
+ inv[15] = entries[0] * entries[5] * entries[10] -
+ entries[0] * entries[6] * entries[9] -
+ entries[4] * entries[1] * entries[10] +
+ entries[4] * entries[2] * entries[9] +
+ entries[8] * entries[1] * entries[6] -
+ entries[8] * entries[2] * entries[5];
+
+ float matrixDet = entries[0] * inv[0] + entries[1] * inv[4] + entries[2] * inv[8] + entries[3] * inv[12];
+
+ float matrixDetr = 1.0f / matrixDet;
+
+ float4x4 res;
+ for (unsigned int i = 0; i < 16; i++) {
+ res.entries[i] = inv[i] * matrixDetr;
+ }
+ return res;
+
+ }
+
+
+
+
+
+ //! returns the 3x3 part of the matrix
+ inline __device__ __host__ float3x3 getFloat3x3() {
+ float3x3 ret;
+ ret.m11 = m11; ret.m12 = m12; ret.m13 = m13;
+ ret.m21 = m21; ret.m22 = m22; ret.m23 = m23;
+ ret.m31 = m31; ret.m32 = m32; ret.m33 = m33;
+ return ret;
+ }
+
+ //! sets the 3x3 part of the matrix (other values remain unchanged)
+ inline __device__ __host__ void setFloat3x3(const float3x3 &other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33;
+ }
+
+ //! sets the 4x4 part of the matrix to identity
+ inline __device__ __host__ void setIdentity()
+ {
+ m11 = 1.0f; m12 = 0.0f; m13 = 0.0f; m14 = 0.0f;
+ m21 = 0.0f; m22 = 1.0f; m23 = 0.0f; m24 = 0.0f;
+ m31 = 0.0f; m32 = 0.0f; m33 = 1.0f; m34 = 0.0f;
+ m41 = 0.0f; m42 = 0.0f; m43 = 0.0f; m44 = 1.0f;
+ }
+
+ //! sets the 4x4 part of the matrix to identity
+ inline __device__ __host__ void setValue(float v)
+ {
+ m11 = v; m12 = v; m13 = v; m14 = v;
+ m21 = v; m22 = v; m23 = v; m24 = v;
+ m31 = v; m32 = v; m33 = v; m34 = v;
+ m41 = v; m42 = v; m43 = v; m44 = v;
+ }
+
+ //! returns the 3x4 part of the matrix
+ inline __device__ __host__ float3x4 getFloat3x4() {
+ float3x4 ret;
+ ret.m11 = m11; ret.m12 = m12; ret.m13 = m13; ret.m14 = m14;
+ ret.m21 = m21; ret.m22 = m22; ret.m23 = m23; ret.m24 = m24;
+ ret.m31 = m31; ret.m32 = m32; ret.m33 = m33; ret.m34 = m34;
+ return ret;
+ }
+
+ //! sets the 3x4 part of the matrix (other values remain unchanged)
+ inline __device__ __host__ void setFloat3x4(const float3x4 &other) {
+ m11 = other.m11; m12 = other.m12; m13 = other.m13; m14 = other.m14;
+ m21 = other.m21; m22 = other.m22; m23 = other.m23; m24 = other.m24;
+ m31 = other.m31; m32 = other.m32; m33 = other.m33; m34 = other.m34;
+ }
+
+
+
+
+ inline __device__ __host__ const float* ptr() const {
+ return entries;
+ }
+ inline __device__ __host__ float* ptr() {
+ return entries;
+ }
+
+ union {
+ struct {
+ float m11; float m12; float m13; float m14;
+ float m21; float m22; float m23; float m24;
+ float m31; float m32; float m33; float m34;
+ float m41; float m42; float m43; float m44;
+ };
+ float entries[16];
+ float entries2[4][4];
+ };
+};
+
+
+
+//////////////////////////////
+// matNxM
+//////////////////////////////
+
+template
+class matNxM
+{
+ public:
+
+ //////////////////////////////
+ // Initialization
+ //////////////////////////////
+ inline __device__ __host__ matNxM()
+ {
+ }
+
+ inline __device__ __host__ matNxM(float* values)
+ {
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i& operator=(const matNxM& other)
+ {
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i getIdentity()
+ {
+ matNxM R; R.setIdentity();
+ return R;
+ }
+
+ //////////////////////////////
+ // Conversion
+ //////////////////////////////
+
+ // declare generic constructors for compile time checking of matrix size
+ template
+ explicit inline __device__ __host__ matNxM(const B& other);
+
+ template
+ explicit inline __device__ __host__ matNxM(const B& other0, const B& other1);
+
+ // declare generic casts for compile time checking of matrix size
+ inline __device__ __host__ operator float();
+ inline __device__ __host__ operator float2();
+ inline __device__ __host__ operator float3();
+ inline __device__ __host__ operator float4();
+
+ inline __device__ __host__ operator float2x2();
+ inline __device__ __host__ operator float3x3();
+ inline __device__ __host__ operator float4x4();
+
+ //////////////////////////////
+ // Matrix - Matrix Multiplication
+ //////////////////////////////
+ template
+ inline __device__ __host__ matNxM operator*(const matNxM& other) const
+ {
+ cudaAssert(M == NOther);
+ matNxM res;
+
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i getInverse() const;
+
+ //////////////////////////////
+ // Matrix - Transpose
+ //////////////////////////////
+ inline __device__ __host__ matNxM getTranspose() const
+ {
+ matNxM res;
+
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i operator+(const matNxM& other) const
+ {
+ matNxM res = (*this);
+ res+=other;
+ return res;
+ }
+
+ inline __device__ __host__ matNxM& operator+=(const matNxM& other)
+ {
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i operator-() const
+ {
+ matNxM res = (*this)*(-1.0f);
+ return res;
+ }
+
+ //////////////////////////////
+ // Matrix - Matrix Subtraction
+ //////////////////////////////
+ inline __device__ __host__ matNxM operator-(const matNxM& other) const
+ {
+ matNxM res = (*this);
+ res-=other;
+ return res;
+ }
+
+ inline __device__ __host__ matNxM& operator-=(const matNxM& other)
+ {
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i operator*(const float t) const
+ {
+ matNxM res = (*this);
+ res*=t;
+ return res;
+ }
+
+ inline __device__ __host__ matNxM& operator*=(const float t)
+ {
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i operator/(const float t) const
+ {
+ matNxM res = (*this);
+ res/=t;
+ return res;
+ }
+
+ inline __device__ __host__ matNxM& operator/=(const float t)
+ {
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i
+ inline __device__ __host__ void getBlock(unsigned int xStart, unsigned int yStart, matNxM& res) const
+ {
+ cudaAssert(xStart+NOther <= N && yStart+MOther <= M);
+
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i
+ inline __device__ __host__ void setBlock(matNxM& input, unsigned int xStart, unsigned int yStart)
+ {
+ cudaAssert(xStart+NOther <= N && yStart+MOther <= M);
+
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i
+inline __device__ __host__ matNxM operator*(const float t, const matNxM& mat)
+{
+ matNxM res = mat;
+ res*=t;
+ return res;
+}
+
+//////////////////////////////
+// Matrix Inversion
+//////////////////////////////
+
+template<>
+inline __device__ __host__ float matNxM<3, 3>::det() const
+{
+ const float& m11 = entries2D[0][0];
+ const float& m12 = entries2D[0][1];
+ const float& m13 = entries2D[0][2];
+
+ const float& m21 = entries2D[1][0];
+ const float& m22 = entries2D[1][1];
+ const float& m23 = entries2D[1][2];
+
+ const float& m31 = entries2D[2][0];
+ const float& m32 = entries2D[2][1];
+ const float& m33 = entries2D[2][2];
+
+ return m11*m22*m33 + m12*m23*m31 + m13*m21*m32 - m31*m22*m13 - m32*m23*m11 - m33*m21*m12;
+}
+
+template<>
+inline __device__ __host__ matNxM<3, 3> matNxM<3, 3>::getInverse() const
+{
+ matNxM<3, 3> res;
+ res.entries[0] = entries[4]*entries[8] - entries[5]*entries[7];
+ res.entries[1] = -entries[1]*entries[8] + entries[2]*entries[7];
+ res.entries[2] = entries[1]*entries[5] - entries[2]*entries[4];
+
+ res.entries[3] = -entries[3]*entries[8] + entries[5]*entries[6];
+ res.entries[4] = entries[0]*entries[8] - entries[2]*entries[6];
+ res.entries[5] = -entries[0]*entries[5] + entries[2]*entries[3];
+
+ res.entries[6] = entries[3]*entries[7] - entries[4]*entries[6];
+ res.entries[7] = -entries[0]*entries[7] + entries[1]*entries[6];
+ res.entries[8] = entries[0]*entries[4] - entries[1]*entries[3];
+ return res*(1.0f/det());
+}
+
+template<>
+inline __device__ __host__ float matNxM<2, 2>::det() const
+{
+ return (*this)(0, 0)*(*this)(1, 1)-(*this)(1, 0)*(*this)(0, 1);
+}
+
+template<>
+inline __device__ __host__ matNxM<2, 2> matNxM<2, 2>::getInverse() const
+{
+ matNxM<2, 2> res;
+ res(0, 0) = (*this)(1, 1); res(0, 1) = -(*this)(0, 1);
+ res(1, 0) = -(*this)(1, 0); res(1, 1) = (*this)(0, 0);
+
+ return res*(1.0f/det());
+}
+
+//////////////////////////////
+// Conversion
+//////////////////////////////
+
+// To Matrix from floatNxN
+template<>
+template<>
+inline __device__ __host__ matNxM<1, 1>::matNxM(const float& other)
+{
+ entries[0] = other;
+}
+
+// To Matrix from floatNxN
+template<>
+template<>
+inline __device__ __host__ matNxM<2, 2>::matNxM(const float2x2& other)
+{
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i<4; i++) entries[i] = other.entries[i];
+}
+
+template<>
+template<>
+inline __device__ __host__ matNxM<3, 3>::matNxM(const float3x3& other)
+{
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i<9; i++) entries[i] = other.entries[i];
+}
+
+template<>
+template<>
+inline __device__ __host__ matNxM<4, 4>::matNxM(const float4x4& other)
+{
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i<16; i++) entries[i] = other.entries[i];
+}
+
+template<>
+template<>
+inline __device__ __host__ matNxM<3, 2>::matNxM(const float3& col0, const float3& col1)
+{
+ entries2D[0][0] = col0.x; entries2D[0][1] = col1.x;
+ entries2D[1][0] = col0.y; entries2D[1][1] = col1.y;
+ entries2D[2][0] = col0.z; entries2D[2][1] = col1.z;
+}
+
+// To floatNxM from Matrix
+template<>
+inline __device__ __host__ matNxM<4, 4>::operator float4x4()
+{
+ float4x4 res;
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i<16; i++) res.entries[i] = entries[i];
+ return res;
+}
+
+template<>
+inline __device__ __host__ matNxM<3, 3>::operator float3x3()
+{
+ float3x3 res;
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i<9; i++) res.entries[i] = entries[i];
+ return res;
+}
+
+template<>
+inline __device__ __host__ matNxM<2, 2>::operator float2x2()
+{
+ float2x2 res;
+ __CONDITIONAL_UNROLL__
+ for(unsigned int i = 0; i<4; i++) res.entries[i] = entries[i];
+ return res;
+}
+
+// To Matrix from floatN
+template<>
+template<>
+inline __device__ __host__ matNxM<2, 1>::matNxM(const float2& other)
+{
+ entries[0] = other.x;
+ entries[1] = other.y;
+}
+
+template<>
+template<>
+inline __device__ __host__ matNxM<3, 1>::matNxM(const float3& other)
+{
+ entries[0] = other.x;
+ entries[1] = other.y;
+ entries[2] = other.z;
+}
+
+template<>
+template<>
+inline __device__ __host__ matNxM<4, 1>::matNxM(const float4& other)
+{
+ entries[0] = other.x;
+ entries[1] = other.y;
+ entries[2] = other.z;
+ entries[3] = other.w;
+}
+
+// To floatN from Matrix
+template<>
+inline __device__ __host__ matNxM<1, 1>::operator float()
+{
+ return entries[0];
+}
+
+template<>
+inline __device__ __host__ matNxM<2, 1>::operator float2()
+{
+ return make_float2(entries[0], entries[1]);
+}
+
+template<>
+inline __device__ __host__ matNxM<3, 1>::operator float3()
+{
+ return make_float3(entries[0], entries[1], entries[2]);
+}
+
+inline __device__ __host__ matNxM<4, 1>::operator float4()
+{
+ return make_float4(entries[0], entries[1], entries[2], entries[3]);
+}
+
+//////////////////////////////
+// Typedefs
+//////////////////////////////
+
+typedef matNxM<9, 3> mat9x3;
+typedef matNxM<3, 9> mat3x9;
+
+typedef matNxM<9, 1> mat9x1;
+typedef matNxM<1, 9> mat1x9;
+
+typedef matNxM<6, 6> mat6x6;
+
+typedef matNxM<6, 1> mat6x1;
+typedef matNxM<1, 6> mat1x6;
+
+typedef matNxM<3, 6> mat3x6;
+typedef matNxM<6, 3> mat6x3;
+
+typedef matNxM<4, 4> mat4x4;
+
+typedef matNxM<4, 1> mat4x1;
+typedef matNxM<1, 4> mat1x4;
+
+typedef matNxM<3, 3> mat3x3;
+
+typedef matNxM<2, 3> mat2x3;
+typedef matNxM<3, 2> mat3x2;
+
+typedef matNxM<2, 2> mat2x2;
+
+typedef matNxM<1, 2> mat1x2;
+typedef matNxM<2, 1> mat2x1;
+
+typedef matNxM<1, 3> mat1x3;
+typedef matNxM<3, 1> mat3x1;
+
+typedef matNxM<1, 1> mat1x1;
+
+
+#endif
diff --git a/AnnotationTools/Filter2dAnnotations/filter.cu b/AnnotationTools/Filter2dAnnotations/filter.cu
new file mode 100644
index 0000000..cff8af4
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/filter.cu
@@ -0,0 +1,1109 @@
+#ifndef _FILTER_
+#define _FILTER_
+
+#include
+#include
+#include "GlobalDefines.h"
+#include "cuda_SimpleMatrixUtil.h"
+
+
+#define T_PER_BLOCK 16
+#define MINF __int_as_float(0xff800000)
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Convert Float4 Color to UCHAR4
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+__global__ void convertColorFloat4ToUCHAR4Device(uchar4* d_output, float4* d_input, unsigned int width, unsigned int height)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if (x >= width || y >= height) return;
+
+ float4 color = d_input[y*width + x];
+ d_output[y*width + x] = make_uchar4(color.x*255.0f, color.y*255.0f, color.z*255.0f, color.w*255.0f);
+}
+
+extern "C" void convertColorFloat4ToUCHAR4(uchar4* d_output, float4* d_input, unsigned int width, unsigned int height)
+{
+ const dim3 blockSize((width + T_PER_BLOCK - 1) / T_PER_BLOCK, (height + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 gridSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ convertColorFloat4ToUCHAR4Device << > >(d_output, d_input, width, height);
+
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Convert Color to Intensity
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+__global__ void convertColorToIntensityFloatDevice(float* d_output, float4* d_input, unsigned int width, unsigned int height)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if (x >= width || y >= height) return;
+
+ const float4 color = d_input[y*width + x];
+ d_output[y*width + x] = 0.299f*color.x + 0.587f*color.y + 0.114f*color.z;
+}
+
+extern "C" void convertColorToIntensityFloat(float* d_output, float4* d_input, unsigned int width, unsigned int height)
+{
+ const dim3 gridSize((width + T_PER_BLOCK - 1) / T_PER_BLOCK, (height + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ convertColorToIntensityFloatDevice << > >(d_output, d_input, width, height);
+
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Convert Depth to Camera Space Positions
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+__global__ void convertDepthFloatToCameraSpaceFloat4Device(float4* d_output, float* d_input, float4x4 intrinsicsInv,
+ unsigned int width, unsigned int height)
+{
+ const unsigned int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const unsigned int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if (x < width && y < height) {
+ d_output[y*width+x] = make_float4(MINF, MINF, MINF, MINF);
+
+ float depth = d_input[y*width+x];
+
+ if(depth != MINF)
+ {
+ float4 cameraSpace(intrinsicsInv*make_float4((float)x*depth, (float)y*depth, depth, depth));
+ d_output[y*width+x] = make_float4(cameraSpace.x, cameraSpace.y, cameraSpace.w, 1.0f);
+ }
+ }
+}
+
+extern "C" void convertDepthFloatToCameraSpaceFloat4(float4* d_output, float* d_input, float4x4 intrinsicsInv, unsigned int width, unsigned int height)
+{
+ const dim3 gridSize((width + T_PER_BLOCK - 1)/T_PER_BLOCK, (height + T_PER_BLOCK - 1)/T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ convertDepthFloatToCameraSpaceFloat4Device<<>>(d_output, d_input, intrinsicsInv, width, height);
+
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Compute Normal Map
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+__global__ void computeNormalsDevice(float4* d_output, float4* d_input, unsigned int width, unsigned int height)
+{
+ const unsigned int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const unsigned int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if(x >= width || y >= height) return;
+
+ d_output[y*width+x] = make_float4(MINF, MINF, MINF, MINF);
+
+ if(x > 0 && x < width-1 && y > 0 && y < height-1)
+ {
+ const float4 CC = d_input[(y+0)*width+(x+0)];
+ const float4 PC = d_input[(y+1)*width+(x+0)];
+ const float4 CP = d_input[(y+0)*width+(x+1)];
+ const float4 MC = d_input[(y-1)*width+(x+0)];
+ const float4 CM = d_input[(y+0)*width+(x-1)];
+
+ if(CC.x != MINF && PC.x != MINF && CP.x != MINF && MC.x != MINF && CM.x != MINF)
+ {
+ const float3 n = cross(make_float3(PC)-make_float3(MC), make_float3(CP)-make_float3(CM));
+ const float l = length(n);
+
+ if(l > 0.0f)
+ {
+ d_output[y*width+x] = make_float4(n/-l, 1.0f);
+ }
+ }
+ }
+}
+
+extern "C" void computeNormals(float4* d_output, float4* d_input, unsigned int width, unsigned int height)
+{
+ const dim3 gridSize((width + T_PER_BLOCK - 1)/T_PER_BLOCK, (height + T_PER_BLOCK - 1)/T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ computeNormalsDevice<<>>(d_output, d_input, width, height);
+
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+/////////////////////////////////////////////
+// Transform
+/////////////////////////////////////////////
+
+__global__ void transformNormalMapDevice(float4* d_normals, unsigned int imageWidth, unsigned int imageHeight, float4x4 transform)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ const int index = y*imageWidth+x;
+
+ if(x >= 0 && x < imageWidth && y >= 0 && y < imageHeight)
+ {
+ if(d_normals[index].x != MINF)
+ {
+ float3 n = transform.getFloat3x3() * make_float3(d_normals[index].x,d_normals[index].y,d_normals[index].z);
+ d_normals[index] = make_float4(n, 0.0f);
+ }
+ }
+}
+
+extern "C" void transformNormalMap(float4* d_normals, unsigned int imageWidth, unsigned int imageHeight, float4x4 transform)
+{
+ const dim3 gridSize((imageWidth + T_PER_BLOCK - 1)/T_PER_BLOCK, (imageHeight + T_PER_BLOCK - 1)/T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ transformNormalMapDevice<<>>(d_normals, imageWidth, imageHeight, transform);
+ #ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+ #endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Bilateral Filter Float Map
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+inline __device__ float gaussR(float sigma, float dist)
+{
+ return exp(-(dist*dist) / (2.0*sigma*sigma));
+}
+
+inline __device__ float linearR(float sigma, float dist)
+{
+ return max(1.0f, min(0.0f, 1.0f - (dist*dist) / (2.0*sigma*sigma)));
+}
+
+inline __device__ float gaussD(float sigma, int x, int y)
+{
+ return exp(-((x*x + y*y) / (2.0f*sigma*sigma)));
+}
+
+inline __device__ float gaussD(float sigma, int x)
+{
+ return exp(-((x*x) / (2.0f*sigma*sigma)));
+}
+
+__global__ void bilateralFilterFloatMapDevice(float* d_output, float* d_input, float sigmaD, float sigmaR, unsigned int width, unsigned int height)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if (x >= width || y >= height) return;
+
+ const int kernelRadius = (int)ceil(2.0*sigmaD);
+
+ d_output[y*width + x] = MINF;
+
+ float sum = 0.0f;
+ float sumWeight = 0.0f;
+
+ const float depthCenter = d_input[y*width + x];
+ if (depthCenter != MINF)
+ {
+ for (int m = x - kernelRadius; m <= x + kernelRadius; m++)
+ {
+ for (int n = y - kernelRadius; n <= y + kernelRadius; n++)
+ {
+ if (m >= 0 && n >= 0 && m < width && n < height)
+ {
+ const float currentDepth = d_input[n*width + m];
+
+ if (currentDepth != MINF) {
+ const float weight = gaussD(sigmaD, m - x, n - y)*gaussR(sigmaR, currentDepth - depthCenter);
+
+ sumWeight += weight;
+ sum += weight*currentDepth;
+ }
+ }
+ }
+ }
+
+ if (sumWeight > 0.0f) d_output[y*width + x] = sum / sumWeight;
+ }
+}
+
+extern "C" void bilateralFilterFloatMap(float* d_output, float* d_input, float sigmaD, float sigmaR, unsigned int width, unsigned int height)
+{
+ const dim3 gridSize((width + T_PER_BLOCK - 1) / T_PER_BLOCK, (height + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ bilateralFilterFloatMapDevice << > >(d_output, d_input, sigmaD, sigmaR, width, height);
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Bilateral Filter Float4 Map
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+__global__ void bilateralFilterFloat4MapDevice(float4* d_output, float4* d_input, float sigmaD, float sigmaR, unsigned int width, unsigned int height)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if (x >= width || y >= height) return;
+
+ const int kernelRadius = (int)ceil(2.0*sigmaD);
+
+ //d_output[y*width+x] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ d_output[y*width + x] = make_float4(MINF, MINF, MINF, MINF);
+
+ float4 sum = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ float sumWeight = 0.0f;
+
+ const float4 depthCenter = d_input[y*width + x];
+ if (depthCenter.x != MINF) {
+ for (int m = x - kernelRadius; m <= x + kernelRadius; m++)
+ {
+ for (int n = y - kernelRadius; n <= y + kernelRadius; n++)
+ {
+ if (m >= 0 && n >= 0 && m < width && n < height)
+ {
+ const float4 currentDepth = d_input[n*width + m];
+
+ if (currentDepth.x != MINF) {
+ const float weight = gaussD(sigmaD, m - x, n - y)*gaussR(sigmaR, length(currentDepth - depthCenter));
+
+ sum += weight*currentDepth;
+ sumWeight += weight;
+ }
+ }
+ }
+ }
+ }
+ if (sumWeight > 0.0f) d_output[y*width + x] = sum / sumWeight;
+}
+
+extern "C" void bilateralFilterFloat4Map(float4* d_output, float4* d_input, float sigmaD, float sigmaR, unsigned int width, unsigned int height)
+{
+ const dim3 gridSize((width + T_PER_BLOCK - 1) / T_PER_BLOCK, (height + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ bilateralFilterFloat4MapDevice << > >(d_output, d_input, sigmaD, sigmaR, width, height);
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Gauss Filter Float Map
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+__global__ void gaussFilterFloatMapDevice(float* d_output, float* d_input, float sigmaD, float sigmaR, unsigned int width, unsigned int height)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if (x >= width || y >= height) return;
+
+ const int kernelRadius = (int)ceil(2.0*sigmaD);
+
+ d_output[y*width + x] = MINF;
+
+ float sum = 0.0f;
+ float sumWeight = 0.0f;
+
+ const float depthCenter = d_input[y*width + x];
+ if (depthCenter != MINF)
+ {
+ for (int m = x - kernelRadius; m <= x + kernelRadius; m++)
+ {
+ for (int n = y - kernelRadius; n <= y + kernelRadius; n++)
+ {
+ if (m >= 0 && n >= 0 && m < width && n < height)
+ {
+ const float currentDepth = d_input[n*width + m];
+
+ if (currentDepth != MINF && fabs(depthCenter - currentDepth) < sigmaR)
+ {
+ const float weight = gaussD(sigmaD, m - x, n - y);
+
+ sumWeight += weight;
+ sum += weight*currentDepth;
+ }
+ }
+ }
+ }
+ }
+
+ if (sumWeight > 0.0f) d_output[y*width + x] = sum / sumWeight;
+}
+
+extern "C" void gaussFilterFloatMap(float* d_output, float* d_input, float sigmaD, float sigmaR, unsigned int width, unsigned int height)
+{
+ const dim3 gridSize((width + T_PER_BLOCK - 1) / T_PER_BLOCK, (height + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ gaussFilterFloatMapDevice << > >(d_output, d_input, sigmaD, sigmaR, width, height);
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Gauss Filter Float4 Map
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+__global__ void gaussFilterFloat4MapDevice(float4* d_output, float4* d_input, float sigmaD, float sigmaR, unsigned int width, unsigned int height)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if (x >= width || y >= height) return;
+
+ const int kernelRadius = (int)ceil(2.0*sigmaD);
+
+ //d_output[y*width+x] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ d_output[y*width + x] = make_float4(MINF, MINF, MINF, MINF);
+
+ float4 sum = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ float sumWeight = 0.0f;
+
+ const float4 center = d_input[y*width + x];
+ if (center.x != MINF) {
+ for (int m = x - kernelRadius; m <= x + kernelRadius; m++)
+ {
+ for (int n = y - kernelRadius; n <= y + kernelRadius; n++)
+ {
+ if (m >= 0 && n >= 0 && m < width && n < height)
+ {
+ const float4 current = d_input[n*width + m];
+
+ if (current.x != MINF) {
+ if (length(center - current) < sigmaR)
+ {
+ const float weight = gaussD(sigmaD, m - x, n - y);
+
+ sumWeight += weight;
+ sum += weight*current;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (sumWeight > 0.0f) d_output[y*width + x] = sum / sumWeight;
+}
+
+extern "C" void gaussFilterFloat4Map(float4* d_output, float4* d_input, float sigmaD, float sigmaR, unsigned int width, unsigned int height)
+{
+ const dim3 gridSize((width + T_PER_BLOCK - 1) / T_PER_BLOCK, (height + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ gaussFilterFloat4MapDevice << > >(d_output, d_input, sigmaD, sigmaR, width, height);
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Compute Edge Mask
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+__global__ void computeMaskEdgeMapFloat4Device(unsigned char* d_output, float4* d_input, float* d_indepth, float threshold, unsigned int width, unsigned int height)
+{
+ const unsigned int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const unsigned int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if (x >= width || y >= height) return;
+
+ d_output[y*width + x] = 1;
+ d_output[width*height + y*width + x] = 1;
+
+ const float thre = threshold *threshold *3.0f;
+ if (x > 0 && y > 0 && x < width - 1 && y < height - 1)
+ {
+ if (d_indepth[y*width + x] == MINF)
+ {
+ d_output[y*width + x] = 0;
+ d_output[y*width + x - 1] = 0;
+ d_output[width*height + y*width + x] = 0;
+ d_output[width*height + (y - 1)*width + x] = 0;
+
+ return;
+ }
+
+ const float4& p0 = d_input[(y + 0)*width + (x + 0)];
+ const float4& p1 = d_input[(y + 0)*width + (x + 1)];
+ const float4& p2 = d_input[(y + 1)*width + (x + 0)];
+
+ float dU = sqrt(((p1.x - p0.x)*(p1.x - p0.x) + (p1.y - p0.y) * (p1.y - p0.y) + (p1.z - p0.z)*(p1.z - p0.z)) / 3.0f);
+ float dV = sqrt(((p2.x - p0.x)*(p2.x - p0.x) + (p2.y - p0.y) * (p2.y - p0.y) + (p2.z - p0.z)*(p2.z - p0.z)) / 3.0f);
+
+ //float dgradx = abs(d_indepth[y*width+x-1] + d_indepth[y*width+x+1] - 2.0f * d_indepth[y*width+x]);
+ //float dgrady = abs(d_indepth[y*width+x-width] + d_indepth[y*width+x+width] - 2.0f * d_indepth[y*width+x]);
+
+
+ if (dU > thre) d_output[y*width + x] = 0;
+ if (dV > thre) d_output[width*height + y*width + x] = 0;
+
+ //remove depth discontinuities
+ const int r = 1;
+ const float thres = 0.01f;
+
+ const float pCC = d_indepth[y*width + x];
+ for (int i = -r; i <= r; i++)
+ {
+ for (int j = -r; j <= r; j++)
+ {
+ int currentX = x + j;
+ int currentY = y + i;
+
+ if (currentX >= 0 && currentX < width && currentY >= 0 && currentY < height)
+ {
+ float d = d_indepth[currentY*width + currentX];
+
+ if (d != MINF && abs(pCC - d) > thres)
+ {
+ d_output[y*width + x] = 0;
+ d_output[width*height + y*width + x] = 0;
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+
+extern "C" void computeMaskEdgeMapFloat4(unsigned char* d_output, float4* d_input, float* d_indepth, float threshold, unsigned int width, unsigned int height)
+{
+ const dim3 gridSize((width + T_PER_BLOCK - 1) / T_PER_BLOCK, (height + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ computeMaskEdgeMapFloat4Device << > >(d_output, d_input, d_indepth, threshold, width, height);
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Resample Float Map
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+inline __device__ float bilinearInterpolationFloat(float x, float y, float* d_input, unsigned int imageWidth, unsigned int imageHeight)
+{
+ const int2 p00 = make_int2(floor(x), floor(y));
+ const int2 p01 = p00 + make_int2(0.0f, 1.0f);
+ const int2 p10 = p00 + make_int2(1.0f, 0.0f);
+ const int2 p11 = p00 + make_int2(1.0f, 1.0f);
+
+ const float alpha = x - p00.x;
+ const float beta = y - p00.y;
+
+ float s0 = 0.0f; float w0 = 0.0f;
+ if (p00.x < imageWidth && p00.y < imageHeight) { float v00 = d_input[p00.y*imageWidth + p00.x]; if (v00 != MINF) { s0 += (1.0f - alpha)*v00; w0 += (1.0f - alpha); } }
+ if (p10.x < imageWidth && p10.y < imageHeight) { float v10 = d_input[p10.y*imageWidth + p10.x]; if (v10 != MINF) { s0 += alpha *v10; w0 += alpha; } }
+
+ float s1 = 0.0f; float w1 = 0.0f;
+ if (p01.x < imageWidth && p01.y < imageHeight) { float v01 = d_input[p01.y*imageWidth + p01.x]; if (v01 != MINF) { s1 += (1.0f - alpha)*v01; w1 += (1.0f - alpha); } }
+ if (p11.x < imageWidth && p11.y < imageHeight) { float v11 = d_input[p11.y*imageWidth + p11.x]; if (v11 != MINF) { s1 += alpha *v11; w1 += alpha; } }
+
+ const float p0 = s0 / w0;
+ const float p1 = s1 / w1;
+
+ float ss = 0.0f; float ww = 0.0f;
+ if (w0 > 0.0f) { ss += (1.0f - beta)*p0; ww += (1.0f - beta); }
+ if (w1 > 0.0f) { ss += beta *p1; ww += beta; }
+
+ if (ww > 0.0f) return ss / ww;
+ else return MINF;
+}
+
+__global__ void resampleFloatMapDevice(float* d_colorMapResampledFloat, float* d_colorMapFloat, unsigned int inputWidth, unsigned int inputHeight, unsigned int outputWidth, unsigned int outputHeight)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if (x < outputWidth && y < outputHeight)
+ {
+ const float scaleWidth = (float)(inputWidth - 1) / (float)(outputWidth - 1);
+ const float scaleHeight = (float)(inputHeight - 1) / (float)(outputHeight - 1);
+
+ const unsigned int xInput = (unsigned int)(x*scaleWidth + 0.5f);
+ const unsigned int yInput = (unsigned int)(y*scaleHeight + 0.5f);
+
+ if (xInput < inputWidth && yInput < inputHeight)
+ {
+ d_colorMapResampledFloat[y*outputWidth + x] = bilinearInterpolationFloat((float)x*scaleWidth, (float)y*scaleHeight, d_colorMapFloat, inputWidth, inputHeight);
+ }
+ }
+}
+
+extern "C" void resampleFloatMap(float* d_colorMapResampledFloat, unsigned int outputWidth, unsigned int outputHeight, float* d_colorMapFloat, unsigned int inputWidth, unsigned int inputHeight)
+{
+ const dim3 gridSize((outputWidth + T_PER_BLOCK - 1) / T_PER_BLOCK, (outputHeight + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ resampleFloatMapDevice << > >(d_colorMapResampledFloat, d_colorMapFloat, inputWidth, inputHeight, outputWidth, outputHeight);
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Resample Float4 Map
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+inline __device__ float4 bilinearInterpolationFloat4(float x, float y, float4* d_input, unsigned int imageWidth, unsigned int imageHeight)
+{
+ const int2 p00 = make_int2(floor(x), floor(y));
+ const int2 p01 = p00 + make_int2(0.0f, 1.0f);
+ const int2 p10 = p00 + make_int2(1.0f, 0.0f);
+ const int2 p11 = p00 + make_int2(1.0f, 1.0f);
+
+ const float alpha = x - p00.x;
+ const float beta = y - p00.y;
+
+ //const float INVALID = 0.0f;
+ const float INVALID = MINF;
+
+ float4 s0 = make_float4(0.0f, 0.0f, 0.0f, 0.0f); float w0 = 0.0f;
+ if (p00.x < imageWidth && p00.y < imageHeight) { float4 v00 = d_input[p00.y*imageWidth + p00.x]; if (v00.x != INVALID && v00.y != INVALID && v00.z != INVALID) { s0 += (1.0f - alpha)*v00; w0 += (1.0f - alpha); } }
+ if (p10.x < imageWidth && p10.y < imageHeight) { float4 v10 = d_input[p10.y*imageWidth + p10.x]; if (v10.x != INVALID && v10.y != INVALID && v10.z != INVALID) { s0 += alpha *v10; w0 += alpha; } }
+
+ float4 s1 = make_float4(0.0f, 0.0f, 0.0f, 0.0f); float w1 = 0.0f;
+ if (p01.x < imageWidth && p01.y < imageHeight) { float4 v01 = d_input[p01.y*imageWidth + p01.x]; if (v01.x != INVALID && v01.y != INVALID && v01.z != INVALID) { s1 += (1.0f - alpha)*v01; w1 += (1.0f - alpha); } }
+ if (p11.x < imageWidth && p11.y < imageHeight) { float4 v11 = d_input[p11.y*imageWidth + p11.x]; if (v11.x != INVALID && v11.y != INVALID && v11.z != INVALID) { s1 += alpha *v11; w1 += alpha; } }
+
+ const float4 p0 = s0 / w0;
+ const float4 p1 = s1 / w1;
+
+ float4 ss = make_float4(0.0f, 0.0f, 0.0f, 0.0f); float ww = 0.0f;
+ if (w0 > 0.0f) { ss += (1.0f - beta)*p0; ww += (1.0f - beta); }
+ if (w1 > 0.0f) { ss += beta *p1; ww += beta; }
+
+ if (ww > 0.0f) return ss / ww;
+ else return make_float4(MINF, MINF, MINF, MINF);
+}
+
+__global__ void resampleFloat4MapDevice(float4* d_colorMapResampledFloat4, float4* d_colorMapFloat4, unsigned int inputWidth, unsigned int inputHeight, unsigned int outputWidth, unsigned int outputHeight)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if (x < outputWidth && y < outputHeight)
+ {
+ const float scaleWidth = (float)(inputWidth - 1) / (float)(outputWidth - 1);
+ const float scaleHeight = (float)(inputHeight - 1) / (float)(outputHeight - 1);
+
+ const unsigned int xInput = (unsigned int)(x*scaleWidth + 0.5f);
+ const unsigned int yInput = (unsigned int)(y*scaleHeight + 0.5f);
+
+ if (xInput < inputWidth && yInput < inputHeight)
+ {
+ d_colorMapResampledFloat4[y*outputWidth + x] = bilinearInterpolationFloat4(x*scaleWidth, y*scaleHeight, d_colorMapFloat4, inputWidth, inputHeight);
+ }
+ }
+}
+
+extern "C" void resampleFloat4Map(float4* d_colorMapResampledFloat4, unsigned int outputWidth, unsigned int outputHeight, float4* d_colorMapFloat4, unsigned int inputWidth, unsigned int inputHeight)
+{
+ const dim3 gridSize((outputWidth + T_PER_BLOCK - 1) / T_PER_BLOCK, (outputHeight + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ resampleFloat4MapDevice << > >(d_colorMapResampledFloat4, d_colorMapFloat4, inputWidth, inputHeight, outputWidth, outputHeight);
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Resample Unsigned Char Map
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+__global__ void resampleUCharMapDevice(unsigned char* d_MapResampled, unsigned int outputWidth, unsigned int outputHeight,
+ unsigned char* d_Map, unsigned int inputWidth, unsigned int inputHeight)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if (x < outputWidth && y < outputHeight)
+ {
+ const float scaleWidth = (float)(inputWidth - 1) / (float)(outputWidth - 1);
+ const float scaleHeight = (float)(inputHeight - 1) / (float)(outputHeight - 1);
+
+ const unsigned int xInput = (unsigned int)(x*scaleWidth + 0.5f);
+ const unsigned int yInput = (unsigned int)(y*scaleHeight + 0.5f);
+
+ if (xInput < inputWidth && yInput < inputHeight)
+ {
+ d_MapResampled[y*outputWidth + x] = d_Map[yInput*inputWidth + xInput];
+ }
+ }
+}
+
+extern "C" void resampleUCharMap(unsigned char* d_MapResampled, unsigned int outputWidth, unsigned int outputHeight,
+ unsigned char* d_Map, unsigned int inputWidth, unsigned int inputHeight)
+{
+ const dim3 gridSize((outputWidth + T_PER_BLOCK - 1) / T_PER_BLOCK, (outputHeight + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ resampleUCharMapDevice << > >(d_MapResampled, outputWidth, outputHeight, d_Map, inputWidth, inputHeight);
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Convert Edge Mask to Float Map
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+__global__ void convertEdgeMaskToFloatDevice(float* d_output, unsigned char* d_input, unsigned int width, unsigned int height)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if (x >= width || y >= height) return;
+
+ d_output[y*width + x] = min(d_input[y*width + x], d_input[width*height + y*width + x]);
+}
+
+extern "C" void convertEdgeMaskToFloat(float* d_output, unsigned char* d_input, unsigned int width, unsigned int height)
+{
+ const dim3 gridSize((width + T_PER_BLOCK - 1) / T_PER_BLOCK, (height + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ convertEdgeMaskToFloatDevice << > >(d_output, d_input, width, height);
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Dilate Depth Map
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+__global__ void dilateDepthMapDevice(float* d_output, float* d_input, float* d_inputOrig, int structureSize, int width, int height)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if (x >= 0 && x < width && y >= 0 && y < height)
+ {
+ float sum = 0.0f;
+ float count = 0.0f;
+ float oldDepth = d_inputOrig[y*width + x];
+ if (oldDepth != MINF && oldDepth != 0)
+ {
+ for (int i = -structureSize; i <= structureSize; i++)
+ {
+ for (int j = -structureSize; j <= structureSize; j++)
+ {
+ if (x + j >= 0 && x + j < width && y + i >= 0 && y + i < height)
+ {
+ const float d = d_input[(y + i)*width + (x + j)];
+
+ if (d != MINF && d != 0.0f && fabs(d - oldDepth) < 0.05f)
+ {
+ sum += d;
+ count += 1.0f;
+ }
+ }
+ }
+ }
+ }
+
+ if (count > ((2 * structureSize + 1)*(2 * structureSize + 1)) / 36) d_output[y*width + x] = 1.0f;
+ else d_output[y*width + x] = MINF;
+ }
+}
+
+extern "C" void dilateDepthMapMask(float* d_output, float* d_input, float* d_inputOrig, int structureSize, int width, int height)
+{
+ const dim3 gridSize((width + T_PER_BLOCK - 1) / T_PER_BLOCK, (height + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ dilateDepthMapDevice << > >(d_output, d_input, d_inputOrig, structureSize, width, height);
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Mean Filter Depth Map
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+__global__ void removeDevMeanMapMaskDevice(float* d_output, float* d_input, int structureSize, int width, int height)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ d_output[y*width + x] = d_input[y*width + x];
+
+ if (x >= 0 && x < width && y >= 0 && y < height)
+ {
+ float oldDepth = d_input[y*width + x];
+
+ float mean = 0.0f;
+ float meanSquared = 0.0f;
+ float count = 0.0f;
+ for (int i = -structureSize; i <= structureSize; i++)
+ {
+ for (int j = -structureSize; j <= structureSize; j++)
+ {
+ if (x + j >= 0 && x + j < width && y + i >= 0 && y + i < height)
+ {
+ float depth = d_input[(y + i)*width + (x + j)];
+ if (depth == MINF)
+ {
+ depth = 8.0f;
+ }
+
+ if (depth > 0.0f)
+ {
+ mean += depth;
+ meanSquared += depth*depth;
+ count += 1.0f;
+ }
+ }
+ }
+ }
+
+ mean /= count;
+ meanSquared /= count;
+
+ float stdDev = sqrt(meanSquared - mean*mean);
+
+ if (fabs(oldDepth - mean) > 0.5f*stdDev)// || stdDev> 0.005f)
+ {
+ d_output[y*width + x] = MINF;
+ }
+ }
+}
+
+extern "C" void removeDevMeanMapMask(float* d_output, float* d_input, int structureSize, unsigned int width, unsigned int height)
+{
+ const dim3 gridSize((width + T_PER_BLOCK - 1) / T_PER_BLOCK, (height + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ removeDevMeanMapMaskDevice << > >(d_output, d_input, structureSize, width, height);
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+
+
+
+// Nearest neighbour
+inline __device__ bool getValueNearestNeighbourNoCheck(const float2& p, const float4* inputMap, unsigned int imageWidth, unsigned int imageHeight, float4* outValue)
+{
+ const int u = (int)(p.x + 0.5f);
+ const int v = (int)(p.y + 0.5f);
+
+ if (u < 0 || u > imageWidth || v < 0 || v > imageHeight) return false;
+
+ *outValue = inputMap[v*imageWidth + u];
+
+ return true;
+}
+
+inline __device__ bool getValueNearestNeighbour(const float2& p, const float4* inputMap, unsigned int imageWidth, unsigned int imageHeight, float4* outValue)
+{
+ bool valid = getValueNearestNeighbourNoCheck(p, inputMap, imageWidth, imageHeight, outValue);
+ return valid && (outValue->x != MINF && outValue->y != MINF && outValue->z != MINF);
+}
+
+// Nearest neighbour
+inline __device__ bool getValueNearestNeighbourFloatNoCheck(const float2& p, const float* inputMap, unsigned int imageWidth, unsigned int imageHeight, float* outValue)
+{
+ const int u = (int)(p.x + 0.5f);
+ const int v = (int)(p.y + 0.5f);
+
+ if (u < 0 || u > imageWidth || v < 0 || v > imageHeight) return false;
+
+ *outValue = inputMap[v*imageWidth + u];
+
+ return true;
+}
+
+inline __device__ bool getValueNearestNeighbourFloat(const float2& p, const float* inputMap, unsigned int imageWidth, unsigned int imageHeight, float* outValue)
+{
+ bool valid = getValueNearestNeighbourFloatNoCheck(p, inputMap, imageWidth, imageHeight, outValue);
+ return valid && (*outValue != MINF);
+}
+
+/////////////////////////////////////////////
+// Compute Intensity and Derivatives
+/////////////////////////////////////////////
+
+__global__ void computeIntensityAndDerivativesDevice(float* d_intensity, unsigned int imageWidth, unsigned int imageHeight, float4* d_intensityAndDerivatives)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ const int index = y*imageWidth + x;
+
+ if (x >= 0 && x < imageWidth && y >= 0 && y < imageHeight)
+ {
+ d_intensityAndDerivatives[index] = make_float4(MINF, MINF, MINF, MINF);
+
+ if (x > 0 && x < imageWidth - 1 && y > 0 && y < imageHeight - 1)
+ {
+ float pos00; bool valid00 = getValueNearestNeighbourFloat(make_float2(x - 1, y - 1), d_intensity, imageWidth, imageHeight, &pos00); if (!valid00) return;
+ float pos01; bool valid01 = getValueNearestNeighbourFloat(make_float2(x - 1, y - 0), d_intensity, imageWidth, imageHeight, &pos01); if (!valid01) return;
+ float pos02; bool valid02 = getValueNearestNeighbourFloat(make_float2(x - 1, y + 1), d_intensity, imageWidth, imageHeight, &pos02); if (!valid02) return;
+
+ float pos10; bool valid10 = getValueNearestNeighbourFloat(make_float2(x - 0, y - 1), d_intensity, imageWidth, imageHeight, &pos10); if (!valid10) return;
+ float pos11; bool valid11 = getValueNearestNeighbourFloat(make_float2(x - 0, y - 0), d_intensity, imageWidth, imageHeight, &pos11); if (!valid11) return;
+ float pos12; bool valid12 = getValueNearestNeighbourFloat(make_float2(x - 0, y + 1), d_intensity, imageWidth, imageHeight, &pos12); if (!valid12) return;
+
+ float pos20; bool valid20 = getValueNearestNeighbourFloat(make_float2(x + 1, y - 1), d_intensity, imageWidth, imageHeight, &pos20); if (!valid20) return;
+ float pos21; bool valid21 = getValueNearestNeighbourFloat(make_float2(x + 1, y - 0), d_intensity, imageWidth, imageHeight, &pos21); if (!valid21) return;
+ float pos22; bool valid22 = getValueNearestNeighbourFloat(make_float2(x + 1, y + 1), d_intensity, imageWidth, imageHeight, &pos22); if (!valid22) return;
+
+ float resU = (-1.0f)*pos00 + (1.0f)*pos20 +
+ (-2.0f)*pos01 + (2.0f)*pos21 +
+ (-1.0f)*pos02 + (1.0f)*pos22;
+ resU /= 8.0f;
+
+ float resV = (-1.0f)*pos00 + (-2.0f)*pos10 + (-1.0f)*pos20 +
+ (1.0f)*pos02 + (2.0f)*pos12 + (1.0f)*pos22;
+ resV /= 8.0f;
+
+ d_intensityAndDerivatives[index] = make_float4(pos11, resU, resV, 1.0f);
+ }
+ }
+}
+
+extern "C" void computeIntensityAndDerivatives(float* d_intensity, unsigned int imageWidth, unsigned int imageHeight, float4* d_intensityAndDerivatives)
+{
+ const dim3 gridSize((imageWidth + T_PER_BLOCK - 1) / T_PER_BLOCK, (imageHeight + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ computeIntensityAndDerivativesDevice << > >(d_intensity, imageWidth, imageHeight, d_intensityAndDerivatives);
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+
+/////////////////////////////////////////////
+// Compute grdient intensity magnitude
+/////////////////////////////////////////////
+
+__global__ void computeGradientIntensityMagnitudeDevice(float4* d_inputDU, float4* d_inputDV, unsigned int imageWidth, unsigned int imageHeight, float4* d_ouput)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ const int index = y*imageWidth + x;
+
+ d_ouput[index] = make_float4(MINF, MINF, MINF, MINF);
+
+ float4 DU = d_inputDU[index];
+ float4 DV = d_inputDV[index];
+
+ if (DU.x != MINF && DV.x != MINF)
+ {
+ float m = sqrtf(DU.x*DU.x + DV.x*DV.x);
+
+ if (m > 0.005f)
+ {
+ d_ouput[index] = make_float4(m, m, m, 1.0f);
+ }
+ }
+}
+
+extern "C" void computeGradientIntensityMagnitude(float4* d_inputDU, float4* d_inputDV, unsigned int imageWidth, unsigned int imageHeight, float4* d_ouput)
+{
+ const dim3 gridSize((imageWidth + T_PER_BLOCK - 1) / T_PER_BLOCK, (imageHeight + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ computeGradientIntensityMagnitudeDevice << > >(d_inputDU, d_inputDV, imageWidth, imageHeight, d_ouput);
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Erode Depth Map
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+__global__ void erodeDepthMapDevice(float* d_output, float* d_input, int structureSize, int width, int height, float dThresh, float fracReq)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+
+ if (x >= 0 && x < width && y >= 0 && y < height)
+ {
+
+
+ unsigned int count = 0;
+
+ float oldDepth = d_input[y*width + x];
+ for (int i = -structureSize; i <= structureSize; i++)
+ {
+ for (int j = -structureSize; j <= structureSize; j++)
+ {
+ if (x + j >= 0 && x + j < width && y + i >= 0 && y + i < height)
+ {
+ float depth = d_input[(y + i)*width + (x + j)];
+ if (depth == MINF || depth == 0.0f || fabs(depth - oldDepth) > dThresh)
+ {
+ count++;
+ //d_output[y*width+x] = MINF;
+ //return;
+ }
+ }
+ }
+ }
+
+ unsigned int sum = (2 * structureSize + 1)*(2 * structureSize + 1);
+ if ((float)count / (float)sum >= fracReq) {
+ d_output[y*width + x] = MINF;
+ }
+ else {
+ d_output[y*width + x] = d_input[y*width + x];
+ }
+ }
+}
+
+extern "C" void erodeDepthMap(float* d_output, float* d_input, int structureSize, unsigned int width, unsigned int height, float dThresh, float fracReq)
+{
+ const dim3 gridSize((width + T_PER_BLOCK - 1) / T_PER_BLOCK, (height + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ erodeDepthMapDevice << > >(d_output, d_input, structureSize, width, height, dThresh, fracReq);
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// filter annotations
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+__global__ void filterAnnotations_Kernel(unsigned char* d_outputInstance, const unsigned char* d_inputInstance,
+ const float* d_depth, const float* d_intensity, const unsigned char* d_instanceToIdx,
+ const unsigned char* d_idxToInstance, float* d_vote,
+ int structureSize, int width, int height, float sigmaD, float sigmaR, float intensityScale)
+{
+ const int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const int y = blockIdx.y*blockDim.y + threadIdx.y;
+ const int voteoffset = (y*width + x) * MAX_NUM_LABELS_PER_SCENE;
+
+ if (x >= 0 && x < width && y >= 0 && y < height) {
+ d_outputInstance[y*width + x] = d_inputInstance[y*width + x];
+ float depthCenter = d_depth[y*width + x];
+ float intensityCenter = d_intensity[y*width + x];
+ for (int i = -structureSize; i <= structureSize; i++) {
+ for (int j = -structureSize; j <= structureSize; j++) {
+ if (x + j >= 0 && x + j < width && y + i >= 0 && y + i < height)
+ {
+ float depth = d_depth[(y + i)*width + (x + j)];
+ float intensity = d_intensity[(y + i)*width + (x + j)];
+ float intensityOffset = std::abs(intensityCenter - intensity) * intensityScale; //bring intensity to approx scale of depth
+ float depthOffset = 0.0f;
+ if (depthCenter != MINF && depth != MINF)
+ depthOffset = std::abs(depthCenter - depth);
+ const float weight = gaussD(sigmaD, j, i)*gaussR(sigmaR, depthOffset)*gaussR(sigmaR, intensityOffset);
+ unsigned char val = d_inputInstance[(y + i)*width + (x + j)];
+ unsigned char idx = d_instanceToIdx[val];
+ d_vote[voteoffset + idx] += weight;
+ }
+ } //j
+ } //i
+ float maxWeight = 0.0f; unsigned char bestVal = 0; //TODO fix this part...
+ for (int i = 0; i < MAX_NUM_LABELS_PER_SCENE; i++) {
+ if (d_vote[voteoffset + i] > maxWeight) {
+ maxWeight = d_vote[voteoffset + i];
+ bestVal = d_idxToInstance[i];
+ }
+ }
+ d_outputInstance[y*width + x] = bestVal;
+ } //in bounds of image
+}
+
+extern "C" void filterAnnotations(unsigned char* d_outputInstance, const unsigned char* d_inputInstance,
+ const float* d_depth, const float* d_intensity, const unsigned char* d_instanceToIdx,
+ const unsigned char* d_idxToInstance, float* d_vote,
+ int structureSize, int width, int height, float sigmaD, float sigmaR, float intensityScale)
+{
+ const dim3 gridSize((width + T_PER_BLOCK - 1) / T_PER_BLOCK, (height + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ cutilSafeCall(cudaMemset(d_vote, 0, sizeof(float)*width*height*MAX_NUM_LABELS_PER_SCENE));
+
+ filterAnnotations_Kernel << > >(d_outputInstance, d_inputInstance,
+ d_depth, d_intensity, d_instanceToIdx, d_idxToInstance, d_vote,
+ structureSize, width, height, sigmaD, sigmaR, intensityScale);
+
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+
+__global__ void convertInstanceToLabel_Kernel(unsigned short* d_outputLabel, const unsigned char* d_inputInstance,
+ const unsigned short* d_instanceToLabel, unsigned int width, unsigned int height)
+{
+ const unsigned int x = blockIdx.x*blockDim.x + threadIdx.x;
+ const unsigned int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+ if (x < width && y < height) {
+ d_outputLabel[y*width + x] = d_instanceToLabel[d_inputInstance[y*width + x]];
+ } //in bounds of image
+}
+
+extern "C" void convertInstanceToLabel(unsigned short* d_outputLabel, const unsigned char* d_inputInstance,
+ const unsigned short* d_instanceToLabel, unsigned int width, unsigned int height)
+{
+ const dim3 gridSize((width + T_PER_BLOCK - 1) / T_PER_BLOCK, (height + T_PER_BLOCK - 1) / T_PER_BLOCK);
+ const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+ convertInstanceToLabel_Kernel << > >(d_outputLabel, d_inputInstance,
+ d_instanceToLabel, width, height);
+
+ //TODO convert instance to label
+#ifdef _DEBUG
+ cutilSafeCall(cudaDeviceSynchronize());
+ cutilCheckMsg(__FUNCTION__);
+#endif
+}
+
+#endif // _FILTER_
diff --git a/AnnotationTools/Filter2dAnnotations/mLibInclude.h b/AnnotationTools/Filter2dAnnotations/mLibInclude.h
new file mode 100644
index 0000000..e3925b2
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/mLibInclude.h
@@ -0,0 +1,24 @@
+
+#ifndef MLIB_INCLUDE_H
+#define MLIB_INCLUDE_H
+
+//
+// mLib config options
+//
+#define MLIB_ERROR_CHECK
+#define MLIB_BOUNDS_CHECK
+
+//
+// mLib includes
+//
+
+#include "mLibCore.h"
+#include "mLibDepthCamera.h"
+//#include "mLibD3D11.h"
+//#include "mLibD3D11Font.h"
+//#include "mLibOpenMesh.h"
+#include "mLibFreeImage.h"
+
+using namespace ml;
+
+#endif
diff --git a/AnnotationTools/Filter2dAnnotations/mLibSource.cpp b/AnnotationTools/Filter2dAnnotations/mLibSource.cpp
new file mode 100644
index 0000000..4ae8cf3
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/mLibSource.cpp
@@ -0,0 +1,6 @@
+
+//#include "stdafx.h"
+
+#include "mLibCore.cpp"
+//#include "mLibD3D11.cpp"
+#include "mLibDepthCamera.cpp"
\ No newline at end of file
diff --git a/AnnotationTools/Filter2dAnnotations/stdafx.cpp b/AnnotationTools/Filter2dAnnotations/stdafx.cpp
new file mode 100644
index 0000000..ba318e9
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/stdafx.cpp
@@ -0,0 +1,9 @@
+// stdafx.cpp : source file that includes just the standard includes
+// EvaluateAnnotations.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
+#include "mLibSource.cpp"
\ No newline at end of file
diff --git a/AnnotationTools/Filter2dAnnotations/stdafx.h b/AnnotationTools/Filter2dAnnotations/stdafx.h
new file mode 100644
index 0000000..988b708
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/stdafx.h
@@ -0,0 +1,16 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include
+#include
+
+
+
+// TODO: reference additional headers your program requires here
+#include "mLibInclude.h"
\ No newline at end of file
diff --git a/AnnotationTools/Filter2dAnnotations/targetver.h b/AnnotationTools/Filter2dAnnotations/targetver.h
new file mode 100644
index 0000000..87c0086
--- /dev/null
+++ b/AnnotationTools/Filter2dAnnotations/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include
diff --git a/AnnotationTools/ProjectAnnotations/GlobalAppState.h b/AnnotationTools/ProjectAnnotations/GlobalAppState.h
new file mode 100644
index 0000000..52c6c15
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/GlobalAppState.h
@@ -0,0 +1,86 @@
+#pragma once
+
+#include "stdafx.h"
+
+#include
+#include
+#include
+
+
+
+#define X_GLOBAL_APP_STATE_FIELDS \
+ X(std::string, s_scanDir) \
+ X(float, s_depthMin) \
+ X(float, s_depthMax) \
+ X(std::string, s_labelMappingFile) \
+ X(std::string, s_outDir) \
+ X(float, s_depthDistThresh) \
+ X(bool, s_useHiResMesh) \
+ X(float, s_propagateNormalThresh) \
+ X(unsigned int, s_frameSkip) \
+ X(bool, s_outputDebugImages) \
+ X(bool, s_filterUsingOrigialDepthImage)
+
+
+#ifndef VAR_NAME
+#define VAR_NAME(x) #x
+#endif
+
+#define checkSizeArray(a, d)( (((sizeof a)/(sizeof a[0])) >= d))
+
+class GlobalAppState
+{
+public:
+
+#define X(type, name) type name;
+ X_GLOBAL_APP_STATE_FIELDS
+#undef X
+
+ //! sets the parameter file and reads
+ void readMembers(const ParameterFile& parameterFile) {
+ m_ParameterFile = parameterFile;
+ readMembers();
+ }
+
+ //! reads all the members from the given parameter file (could be called for reloading)
+ void readMembers() {
+#define X(type, name) \
+ if (!m_ParameterFile.readParameter(std::string(#name), name)) {MLIB_WARNING(std::string(#name).append(" ").append("uninitialized")); name = type();}
+ X_GLOBAL_APP_STATE_FIELDS
+#undef X
+
+
+ m_bIsInitialized = true;
+ }
+
+ void print() const {
+#define X(type, name) \
+ std::cout << #name " = " << name << std::endl;
+ X_GLOBAL_APP_STATE_FIELDS
+#undef X
+ }
+
+ static GlobalAppState& getInstance() {
+ static GlobalAppState s;
+ return s;
+ }
+ static GlobalAppState& get() {
+ return getInstance();
+ }
+
+
+ //! constructor
+ GlobalAppState() {
+ m_bIsInitialized = false;
+ }
+
+ //! destructor
+ ~GlobalAppState() {
+ }
+
+ Timer s_Timer;
+
+private:
+ bool m_bIsInitialized;
+ ParameterFile m_ParameterFile;
+};
diff --git a/AnnotationTools/ProjectAnnotations/LabelUtil.h b/AnnotationTools/ProjectAnnotations/LabelUtil.h
new file mode 100644
index 0000000..1f9d9c3
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/LabelUtil.h
@@ -0,0 +1,89 @@
+#pragma once
+
+class LabelUtil
+{
+public:
+ LabelUtil() {}
+ void init(const std::string& labelMapFile, const std::string& labelName = "category", const std::string& idName = "") {
+ if (!util::fileExists(labelMapFile)) throw MLIB_EXCEPTION(labelMapFile + " does not exist!");
+ m_maxLabel = 65535;//255;
+
+ getLabelMappingFromFile(labelMapFile, labelName, idName);
+
+ m_bIsInitialized = true;
+ }
+
+ static LabelUtil& getInstance() {
+ static LabelUtil s;
+ return s;
+ }
+ static LabelUtil& get() {
+ return getInstance();
+ }
+
+ bool getIdForLabel(const std::string& label, unsigned short& id) const {
+ const auto it = s_labelsToIds.find(label);
+ if (it == s_labelsToIds.end()) return false;
+ id = it->second;
+ return true;
+ }
+
+ bool getLabelForId(unsigned short id, std::string& label) const {
+ const auto it = s_idsToLabels.find(id);
+ if (it == s_idsToLabels.end()) return false;
+ label = it->second;
+ return true;
+ }
+
+private:
+
+ void getLabelMappingFromFile(const std::string& filename, const std::string& labelName, const std::string& idName)
+ {
+ if (!util::fileExists(filename)) throw MLIB_EXCEPTION("label mapping files does not exist!");
+ const char splitter = '\t';
+
+ s_labelsToIds.clear();
+ s_idsToLabels.clear();
+
+ std::ifstream s(filename); std::string line;
+ //read header
+ std::unordered_map header;
+ if (!std::getline(s, line)) throw MLIB_EXCEPTION("error reading label mapping file");
+ auto parts = util::split(line, splitter);
+ const unsigned int numElems = (unsigned int)parts.size();
+ for (unsigned int i = 0; i < parts.size(); i++) header[parts[i]] = i;
+
+ auto it = header.find(labelName);
+ if (it == header.end()) throw MLIB_EXCEPTION("could not find value " + labelName + " in label mapping file");
+ unsigned int labelIdx = it->second;
+ bool bUseExistingLabel = !idName.empty(); unsigned int idIdx = (unsigned int)-1;
+ if (bUseExistingLabel) {
+ it = header.find(idName);
+ if (it == header.end()) throw MLIB_EXCEPTION("could not find value " + idName + " in label mapping file");
+ idIdx = it->second;
+ }
+ //read elements
+ unsigned int lineCount = 1;
+ while (std::getline(s, line)) {
+ parts = util::split(line, splitter, true);
+ if (!parts[labelIdx].empty() && (!bUseExistingLabel || !parts[idIdx].empty())) {
+ unsigned int id = bUseExistingLabel ? util::convertTo(parts[idIdx]) : lineCount;
+ if (id > m_maxLabel) //skip
+ continue;
+ s_labelsToIds[parts[labelIdx]] = (unsigned short)id;
+ s_idsToLabels[(unsigned short)id] = parts[labelIdx];
+ }
+ ++lineCount;
+ }
+ s.close();
+
+ std::cout << "read " << s_labelsToIds.size() << " labels" << std::endl;
+ }
+
+ bool m_bIsInitialized;
+ unsigned short m_maxLabel;
+
+ std::unordered_map s_labelsToIds;
+ std::unordered_map s_idsToLabels;
+
+};
\ No newline at end of file
diff --git a/AnnotationTools/ProjectAnnotations/ProjectAnnotations.sln b/AnnotationTools/ProjectAnnotations/ProjectAnnotations.sln
new file mode 100644
index 0000000..a00469b
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/ProjectAnnotations.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.40629.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProjectAnnotations", "ProjectAnnotations.vcxproj", "{B7522A83-8AE0-4351-BE91-71C5989A6519}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B7522A83-8AE0-4351-BE91-71C5989A6519}.Debug|x64.ActiveCfg = Debug|x64
+ {B7522A83-8AE0-4351-BE91-71C5989A6519}.Debug|x64.Build.0 = Debug|x64
+ {B7522A83-8AE0-4351-BE91-71C5989A6519}.Release|x64.ActiveCfg = Release|x64
+ {B7522A83-8AE0-4351-BE91-71C5989A6519}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/AnnotationTools/ProjectAnnotations/ProjectAnnotations.vcxproj b/AnnotationTools/ProjectAnnotations/ProjectAnnotations.vcxproj
new file mode 100644
index 0000000..bbc3ef9
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/ProjectAnnotations.vcxproj
@@ -0,0 +1,129 @@
+
+
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {B7522A83-8AE0-4351-BE91-71C5989A6519}
+ Win32Proj
+ ProjectAnnotations
+
+
+
+ Application
+ true
+ v120
+ Unicode
+
+
+ Application
+ false
+ v120
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ ../../external/mLib/include;../../../mLibExternal/include;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;$(IncludePath)
+ C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Lib\x64;../../../mLibExternal/libsWindows/lib64;$(LibraryPath)
+
+
+ false
+ ../../external/mLib/include;../../../mLibExternal/include;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;$(IncludePath)
+ C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Lib\x64;../../../mLibExternal/libsWindows/lib64;$(LibraryPath)
+
+
+
+ Use
+ Level3
+ Disabled
+ WIN32;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+ false
+ -Zm110 %(AdditionalOptions)
+
+
+ Console
+ true
+ FW1FontWrapper.lib;d3d11.lib;d3dx11.lib;D3DCompiler.lib;FreeImage.lib;zlib64.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ Use
+ MaxSpeed
+ true
+ true
+ WIN32;_CRT_SECURE_NO_WARNINGS;NOMINMAX;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+ $(IncludePath);$(DXSDK_DIR)Include;..\..\mLibextern\include
+ true
+ -Zm110 %(AdditionalOptions)
+
+
+ Console
+ true
+ true
+ true
+ FW1FontWrapper.lib;d3d11.lib;d3dx11.lib;D3DCompiler.lib;FreeImage.lib;zlib64.lib;%(AdditionalDependencies)
+ $(LibraryPath);$(DXSDK_DIR)Lib\x64; ..\..\mLibextern\libsWindows\lib64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+
+
+ Create
+ Create
+
+
+
+
+
+
+
+
+ true
+ Document
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AnnotationTools/ProjectAnnotations/ProjectAnnotations.vcxproj.filters b/AnnotationTools/ProjectAnnotations/ProjectAnnotations.vcxproj.filters
new file mode 100644
index 0000000..02589a5
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/ProjectAnnotations.vcxproj.filters
@@ -0,0 +1,82 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {8e0e7543-8329-42d8-a2e5-c872d029edc0}
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Resource Files
+
+
+
+
+ Shader
+
+
+
\ No newline at end of file
diff --git a/AnnotationTools/ProjectAnnotations/Visualizer.cpp b/AnnotationTools/ProjectAnnotations/Visualizer.cpp
new file mode 100644
index 0000000..8495f37
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/Visualizer.cpp
@@ -0,0 +1,378 @@
+
+#include "stdafx.h"
+#include "Visualizer.h"
+#include "GlobalAppState.h"
+#include "LabelUtil.h"
+#include "omp.h"
+#include
+
+void Visualizer::init(ApplicationData &app)
+{
+ std::string scanDir = GlobalAppState::get().s_scanDir;
+ scanDir = util::replace(scanDir, '\\', '/');
+ if (scanDir.back() != '/') scanDir.push_back('/');
+ std::cout << "[ProjectAnnotations] " << scanDir << std::endl;
+ const std::string scanName = util::split(scanDir, "/").back();
+ const std::string sensFile = scanDir + scanName + ".sens";
+ const std::string meshFile = scanDir + scanName + "_vh_clean_2.ply";
+ const std::string segsFile = scanDir + scanName + "_vh_clean_2.0.010000.segs.json";
+ const std::string aggregationFile = scanDir + scanName + ".aggregation.json";
+ const std::string meshHiFile = scanDir + scanName + "_vh_clean.ply";
+ const bool bUseHiResMesh = GlobalAppState::get().s_useHiResMesh;
+ if (!(util::fileExists(sensFile) && util::fileExists(meshFile) && util::fileExists(segsFile) &&
+ util::fileExists(aggregationFile) && (!bUseHiResMesh || util::fileExists(meshHiFile)))) {
+ std::cout << "WARNING: no sens/mesh/segs/aggregation file, skipping" << std::endl;
+ return;
+ }
+ LabelUtil::get().init(GlobalAppState::get().s_labelMappingFile);
+
+ m_sensorName = util::removeExtensions(util::splitPath(sensFile).back());
+ std::cout << "loading scan info... "; Timer t;
+ m_sensorData.loadFromFile(sensFile);
+ //load aggregation and compute segmentation ids
+ Segmentation segmentation; segmentation.loadFromFile(segsFile);
+ Aggregation aggregation; aggregation.loadFromJSONFile(aggregationFile);
+
+ MeshDataf meshData = MeshIOf::loadFromFile(meshFile);
+ MeshDataf meshHi; if (bUseHiResMesh) MeshIOf::loadFromFile(meshHiFile, meshHi);
+ unsigned int numObjects = computeObjectIdsAndColorsPerVertex(aggregation, segmentation, meshData, meshHi); //puts hi-res with labels into meshdata
+ m_mesh.init(app.graphics, TriMeshf(meshData));
+ std::cout << "done! (" << t.getElapsedTime() << " s)" << std::endl;
+
+ m_fieldOfView = 2 * 180 / PI * atan(0.5 * m_sensorData.m_colorWidth / m_sensorData.m_calibrationColor.m_intrinsic(0, 0));
+ m_camera = Cameraf(m_sensorData.m_frames[0].getCameraToWorld(), m_fieldOfView,
+ (float)m_sensorData.m_colorWidth / (float)m_sensorData.m_colorHeight, GlobalAppState::get().s_depthMin, GlobalAppState::get().s_depthMax);
+
+ m_constants.init(app.graphics);
+
+ std::vector formats = {
+ DXGI_FORMAT::DXGI_FORMAT_R32G32B32A32_FLOAT
+ };
+ m_renderTarget.init(app.graphics.castD3D11(), m_sensorData.m_colorWidth, m_sensorData.m_colorHeight, formats, true);
+
+ const std::string outDir = GlobalAppState::get().s_outDir;
+ if (!util::directoryExists(outDir)) util::makeDirectory(outDir);
+}
+
+void Visualizer::render(ApplicationData &app)
+{
+ m_timer.frame();
+
+ static unsigned int frame = 0;
+ bool validFrame = false;
+ if (frame < m_sensorData.m_frames.size()) {
+ if (m_sensorData.m_frames[frame].getCameraToWorld()._m00 != -std::numeric_limits::infinity()) validFrame = true;
+ m_camera = Cameraf(m_sensorData.m_frames[frame].getCameraToWorld(), m_fieldOfView,
+ (float)m_sensorData.m_colorWidth / (float)m_sensorData.m_colorHeight, GlobalAppState::get().s_depthMin, GlobalAppState::get().s_depthMax);
+ std::cout << "\r[ " << (frame + 1) << " | " << m_sensorData.m_frames.size() << " ]";
+ }
+ else {
+ std::cout << std::endl << "done" << std::endl;
+ exit(0);
+ }
+
+ std::string outDir = GlobalAppState::get().s_outDir;
+ outDir = (outDir.back() == '/' || outDir.back() == '\\') ? outDir + m_sensorName + "/" : outDir + "/" + m_sensorName + "/";
+ if (!util::directoryExists(outDir)) util::makeDirectory(outDir);
+ const std::string outInstanceDir = outDir + "instance/"; if (!util::directoryExists(outInstanceDir)) util::makeDirectory(outInstanceDir);
+ const std::string outLabelDir = outDir + "label/"; if (!util::directoryExists(outLabelDir)) util::makeDirectory(outLabelDir);
+
+ const bool bFilterUsingOrigDepth = GlobalAppState::get().s_filterUsingOrigialDepthImage;
+ const float zNear = GlobalAppState::get().s_depthMin;
+ const float zFar = GlobalAppState::get().s_depthMax;
+ const float depthDistThresh = GlobalAppState::get().s_depthDistThresh;
+ if (validFrame) {
+ DepthImage16 origDepthImage = m_sensorData.computeDepthImage(frame);
+
+ mat4f proj = Cameraf::visionToGraphicsProj(m_sensorData.m_colorWidth, m_sensorData.m_colorHeight, m_sensorData.m_calibrationColor.m_intrinsic(0, 0), m_sensorData.m_calibrationColor.m_intrinsic(1, 1), zNear, zFar);
+ ConstantBuffer constants;
+ constants.worldViewProj = proj * m_camera.getView();
+
+ constants.modelColor = ml::vec4f(1.0f, 1.0f, 1.0f, 1.0f);
+ m_constants.updateAndBind(constants, 0);
+ app.graphics.castD3D11().getShaderManager().registerShader("shaders/drawAnnotations.hlsl", "drawAnnotations", "vertexShaderMain", "vs_4_0", "pixelShaderMain", "ps_4_0");
+ app.graphics.castD3D11().getShaderManager().bindShaders("drawAnnotations");
+
+ m_renderTarget.clear();
+ m_renderTarget.bind();
+ m_mesh.render();
+ m_renderTarget.unbind();
+
+ DepthImage32 depthBuffer;
+ ColorImageR32G32B32A32 colorBuffer;
+ m_renderTarget.captureColorBuffer(colorBuffer);
+ m_renderTarget.captureDepthBuffer(depthBuffer);
+ //annotations
+ MLIB_ASSERT(colorBuffer.getWidth() == m_sensorData.m_colorWidth && colorBuffer.getHeight() == m_sensorData.m_colorHeight);
+ BaseImage objectInstanceImage(colorBuffer.getWidth(), colorBuffer.getHeight()); // image with object id annotations
+ BaseImage objectLabelImage(colorBuffer.getWidth(), colorBuffer.getHeight());
+ for (unsigned int i = 0; i < colorBuffer.getNumPixels(); i++) {
+ const vec4f& c = colorBuffer.getData()[i];
+ float label = c.w; float id = c.z;
+ label = std::round(label); id = std::round(id);
+ MLIB_ASSERT(label >= 0 && label < 65535 && id >= 0 && id < 255);
+ objectInstanceImage.getData()[i] = (unsigned char)id;
+ objectLabelImage.getData()[i] = (unsigned short)label;
+ }
+
+ //depth
+ mat4f projToCamera = m_camera.getProj().getInverse();
+ mat4f cameraToWorld = m_camera.getView().getInverse();
+ mat4f projToWorld = cameraToWorld * projToCamera;
+ mat4f intrinsic = Cameraf::graphicsToVisionProj(m_camera.getProj(), depthBuffer.getWidth(), depthBuffer.getHeight());
+#pragma omp parallel for
+ for (int y = 0; y < (int)depthBuffer.getHeight(); y++) {
+ for (int x = 0; x < (int)depthBuffer.getWidth(); x++) {
+ float d = depthBuffer(x, y);
+ if (d != 0.0f && d != 1.0f) {
+ vec3f posProj = vec3f(app.graphics.castD3D11().pixelToNDC(vec2i(x, y), depthBuffer.getWidth(), depthBuffer.getHeight()), d);
+ vec3f posCamera = projToCamera * posProj;
+ if (posCamera.z >= zNear && posCamera.z <= zFar) depthBuffer(x, y) = posCamera.z;
+ else depthBuffer(x, y) = 0.0f;
+ }
+ else {
+ depthBuffer(x, y) = 0.0f;
+ }
+ }
+ }
+ DepthImage16 depth(depthBuffer.getResized(m_sensorData.m_depthWidth, m_sensorData.m_depthHeight), 1000.0f);
+
+ const float scaleDepthWidth = (float)(depth.getWidth() - 1) / (float)(objectLabelImage.getWidth() - 1);
+ const float scaleDepthHeight = (float)(depth.getHeight() - 1) / (float)(objectLabelImage.getHeight() - 1);
+#pragma omp parallel for
+ for (int y = 0; y < (int)objectLabelImage.getHeight(); y++) {
+ for (int x = 0; x < (int)objectLabelImage.getWidth(); x++) {
+ unsigned short v = objectLabelImage(x, y);
+ if (v != 0) {
+ const unsigned int dx = (unsigned int)std::round(scaleDepthWidth * x);
+ const unsigned int dy = (unsigned int)std::round(scaleDepthHeight * y);
+ const unsigned short drndr = depth(dx, dy);
+ const unsigned short dorig = origDepthImage(dx, dy);
+ if ((bFilterUsingOrigDepth && dorig == 0) || (drndr != 0 && dorig != 0 && std::fabs((drndr - dorig) * 0.001f) > depthDistThresh + 0.01f * dorig)) {
+ objectLabelImage(x, y) = 0;
+ objectInstanceImage(x, y) = 0;
+ }
+ }
+ } //x
+ } //y
+
+ int radius = 2;
+#pragma omp parallel for
+ for (int y = 0; y < (int)objectLabelImage.getHeight(); y++) {
+ for (int x = 0; x < (int)objectLabelImage.getWidth(); x++) {
+ unsigned short v = objectLabelImage(x, y);
+ if (v != 0) {
+ unsigned int count = 0, total = 0;
+ for (int yy = y - radius; yy <= y + radius; yy++) {
+ for (int xx = x - radius; xx <= x + radius; xx++) {
+ if (xx >= 0 && xx < (int)objectLabelImage.getWidth() && yy >= 0 && yy < (int)objectLabelImage.getHeight()) {
+ total++;
+ if (objectLabelImage(xx, yy) == v) count++;
+ }
+ }
+ }
+ if ((float)count / (float)total < 0.2f) {
+ objectLabelImage(x, y) = 0;
+ objectInstanceImage(x, y) = 0;
+ }
+ }
+ } //x
+ } //y
+
+ FreeImageWrapper::saveImage(outInstanceDir + std::to_string(frame) + ".png", objectInstanceImage);
+ FreeImageWrapper::saveImage(outLabelDir + std::to_string(frame) + ".png", objectLabelImage);
+
+ if (GlobalAppState::get().s_outputDebugImages && frame % 100 == 0) {
+
+ static std::unordered_map colors;
+ for (const auto& p : objectLabelImage) {
+ if (p.value != 0 && colors.find(p.value) == colors.end()) {
+ RGBColor c = RGBColor::randomColor();
+ colors[p.value] = vec3uc(c.x, c.y, c.z);
+ }
+ }
+ for (const auto& p : objectInstanceImage) {
+ if (p.value != 0 && colors.find(p.value) == colors.end()) {
+ RGBColor c = RGBColor::randomColor();
+ colors[p.value] = vec3uc(c.x, c.y, c.z);
+ }
+ }
+
+ //debug print out colored annotation image
+ ColorImageR8G8B8 colorImageInstance(colorBuffer.getWidth(), colorBuffer.getHeight());
+ ColorImageR8G8B8 colorImageLabel(colorBuffer.getWidth(), colorBuffer.getHeight());
+ for (const auto& p : objectLabelImage) {
+ if (p.value != 0) {
+ const auto it = colors.find(p.value);
+ MLIB_ASSERT(it != colors.end());
+ colorImageLabel(p.x, p.y) = it->second;
+ }
+ else colorImageLabel(p.x, p.y) = vec3uc(0, 0, 0);
+ }
+ for (const auto& p : objectInstanceImage) {
+ if (p.value != 0) {
+ const auto it = colors.find(p.value);
+ MLIB_ASSERT(it != colors.end());
+ colorImageInstance(p.x, p.y) = it->second;
+ }
+ else colorImageInstance(p.x, p.y) = vec3uc(0, 0, 0);
+ }
+ FreeImageWrapper::saveImage(outDir + std::to_string(frame) + "_color-label.png", colorImageLabel);
+ FreeImageWrapper::saveImage(outDir + std::to_string(frame) + "_color-instance.png", colorImageInstance);
+ //std::cout << "waiting..." << std::endl; getchar();
+ }
+ }
+ else {
+ BaseImage objectInstanceImage(m_sensorData.m_colorWidth, m_sensorData.m_colorHeight, (unsigned char)0); //empty image, no valid transform
+ BaseImage objectLabelImage(m_sensorData.m_colorWidth, m_sensorData.m_colorHeight, (unsigned short)0); //empty image, no valid transform
+ FreeImageWrapper::saveImage(outInstanceDir + std::to_string(frame) + ".png", objectInstanceImage);
+ FreeImageWrapper::saveImage(outLabelDir + std::to_string(frame) + ".png", objectLabelImage);
+ }
+ frame += GlobalAppState::get().s_frameSkip;
+}
+
+void Visualizer::resize(ApplicationData &app)
+{
+ m_camera.updateAspectRatio((float)app.window.getWidth() / app.window.getHeight());
+}
+
+void Visualizer::keyDown(ApplicationData &app, UINT key)
+{
+}
+
+void Visualizer::keyPressed(ApplicationData &app, UINT key)
+{
+}
+
+void Visualizer::mouseDown(ApplicationData &app, MouseButtonType button)
+{
+}
+
+void Visualizer::mouseWheel(ApplicationData &app, int wheelDelta)
+{
+}
+
+void Visualizer::mouseMove(ApplicationData &app)
+{
+}
+
+unsigned int Visualizer::computeObjectIdsAndColorsPerVertex(const Aggregation& aggregation, const Segmentation& segmentation,
+ MeshDataf& meshData, const MeshDataf& meshHi)
+{
+ const bool bUseHi = !meshHi.isEmpty();
+ std::vector colorsPerVertex(meshData.m_Vertices.size(), vec4f::origin);
+
+ const auto& aggregatedSegments = aggregation.getAggregatedSegments();
+ const auto& objectIdsToLabels = aggregation.getObjectIdsToLabels();
+ //generate some random colors
+ std::unordered_map objectColors; std::unordered_map objectIdsToLabelIds;
+ for (unsigned int i = 0; i < aggregatedSegments.size(); i++) {
+ const unsigned int objectId = i;
+ const auto itl = objectIdsToLabels.find(objectId);
+ MLIB_ASSERT(itl != objectIdsToLabels.end());
+ unsigned short labelId;
+ if (LabelUtil::get().getIdForLabel(itl->second, labelId)) {
+ objectIdsToLabelIds[objectId] = labelId;
+ auto itc = objectColors.find(labelId);
+ if (itc == objectColors.end()) {
+ RGBColor c = RGBColor::randomColor();
+ objectColors[labelId] = vec4f(c.x / 255.0f, c.y / 255.0f, objectId + 1, labelId); //objectid -> instance, labelid-> label
+ }
+ }
+ }
+ //assign object ids and colors
+ std::unordered_map< unsigned int, std::vector > verticesPerSegment = segmentation.getSegmentIdToVertIdMap();
+ for (unsigned int i = 0; i < aggregatedSegments.size(); i++) {
+ const unsigned int objectId = i;
+ const auto itl = objectIdsToLabelIds.find(objectId);
+ if (itl == objectIdsToLabelIds.end()) continue;
+ const vec4f& color = objectColors[itl->second];
+ for (unsigned int seg : aggregatedSegments[i]) {
+ const std::vector& vertIds = verticesPerSegment[seg];
+ for (unsigned int v : vertIds) {
+ colorsPerVertex[v] = color;
+ }
+ }
+ }
+ meshData.m_Colors = colorsPerVertex;
+ if (bUseHi) {
+ MeshDataf propagated = meshHi;
+ if (!meshData.hasNormals()) meshData.computeVertexNormals();
+ if (!propagated.hasNormals()) propagated.computeVertexNormals();
+ propagateAnnotations(meshData, propagated);
+ meshData = propagated;
+ }
+ return (unsigned int)objectColors.size();
+}
+
+void Visualizer::propagateAnnotations(const MeshDataf& meshSrc, MeshDataf& meshDst)
+{
+ MLIB_ASSERT(meshSrc.hasNormals() && meshDst.hasNormals());
+ const float normalThresh = GlobalAppState::get().s_propagateNormalThresh;
+
+ const bbox3f bbox = meshSrc.computeBoundingBox();
+
+ //nearest neighbor search for vertices
+ std::vector searchVerts;
+ std::vector searchIndices;
+ for (unsigned int i = 0; i < meshSrc.m_Vertices.size(); i++) {
+ if (meshSrc.m_Colors[i].w > 0) {
+ searchVerts.push_back(meshSrc.m_Vertices[i]);
+ searchIndices.push_back(i);
+ }
+ }
+ std::vector srcVerts(searchVerts.size());
+ for (unsigned int i = 0; i < searchVerts.size(); i++) {
+ srcVerts[i] = (const float*)&searchVerts[i];
+ }
+ const unsigned int maxK = 3;
+ const float eps = 0.01f;
+ int numThreads = omp_get_max_threads();
+ std::vector nn(numThreads);
+ for (unsigned int i = 0; i < nn.size(); i++) {
+ nn[i] = new NearestNeighborSearchFLANNf(100, 12);
+ nn[i]->init(srcVerts, 3, maxK);
+ }
+ const float maxThresh = std::max(bbox.getMaxExtent() * 0.01f, 0.05f);
+
+ if (!meshDst.hasColors()) meshDst.m_Colors.resize(meshDst.m_Vertices.size());
+#pragma omp parallel for
+ for (int i = 0; i < (int)meshDst.m_Vertices.size(); i++) {
+ int thread = omp_get_thread_num();
+ std::vector nearestIndices;
+ nn[thread]->kNearest((const float*)&meshDst.m_Vertices[i], maxK, eps, nearestIndices);
+ if (!nearestIndices.empty()) {
+ std::vector dists = nn[thread]->getDistances(maxK);
+ unsigned int bestIdx = (unsigned int)-1;
+ const vec4f& val = meshSrc.m_Colors[searchIndices[nearestIndices[0]]]; //object id
+ bool allSame = true;
+ for (unsigned int k = 0; k < maxK; k++) {
+ if (dists[k] < maxThresh) {
+ if (std::acos(math::clamp(meshSrc.m_Normals[searchIndices[nearestIndices[k]]] | meshDst.m_Normals[i], -1.0f, 1.0f)) < normalThresh) { //make sure similar normals
+ bestIdx = k;
+ break;
+ }
+ if (meshSrc.m_Colors[searchIndices[nearestIndices[k]]].z != val.z) allSame = false;
+ }
+ else allSame = false;
+ }
+ if (bestIdx != (unsigned int)-1) {
+ const vec3f& nearest = searchVerts[nearestIndices[bestIdx]];
+ meshDst.m_Colors[i] = meshSrc.m_Colors[searchIndices[nearestIndices[bestIdx]]];
+ }
+ else if (allSame) {
+ meshDst.m_Colors[i] = val;
+ }
+ else {
+ meshDst.m_Colors[i] = vec4f(0.0f);
+ }
+ }
+ else {
+ meshDst.m_Colors[i] = vec4f(0.0f);
+ }
+ }
+ for (unsigned int i = 0; i < nn.size(); i++)
+ SAFE_DELETE(nn[i]);
+}
+
+
diff --git a/AnnotationTools/ProjectAnnotations/Visualizer.h b/AnnotationTools/ProjectAnnotations/Visualizer.h
new file mode 100644
index 0000000..2d71466
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/Visualizer.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include "../common/json.h"
+#include "../common/Segmentation.h"
+#include "../common/Aggregation.h"
+
+struct ConstantBuffer
+{
+ mat4f worldViewProj;
+ ml::vec4f modelColor;
+};
+
+class Visualizer : public ApplicationCallback
+{
+public:
+ void init(ApplicationData &app);
+ void render(ApplicationData &app);
+ void keyDown(ApplicationData &app, UINT key);
+
+ void keyPressed(ApplicationData &app, UINT key);
+ void mouseDown(ApplicationData &app, MouseButtonType button);
+ void mouseMove(ApplicationData &app);
+ void mouseWheel(ApplicationData &app, int wheelDelta);
+ void resize(ApplicationData &app);
+
+private:
+ //returns #unique objects/colors
+ unsigned int computeObjectIdsAndColorsPerVertex(const Aggregation& aggregation, const Segmentation& segmentation, MeshDataf& meshData, const MeshDataf& meshHi);
+
+ static inline float gaussD(float sigma, int x, int y)
+ {
+ return exp(-((x*x + y*y) / (2.0f*sigma*sigma)));
+ }
+ static inline float gaussR(float sigma, float dist)
+ {
+ return exp(-(dist*dist) / (2.0f*sigma*sigma));
+ }
+
+ void propagateAnnotations(const MeshDataf& meshSrc, MeshDataf& meshDst);
+
+ ml::D3D11TriMesh m_mesh;
+
+ ml::D3D11ShaderManager m_shaderManager;
+ D3D11RenderTarget m_renderTarget;
+
+ FrameTimer m_timer;
+
+ D3D11ConstantBuffer m_constants;
+ Cameraf m_camera;
+
+ //scan data
+ SensorData m_sensorData;
+ std::string m_sensorName;
+ float m_fieldOfView;
+};
\ No newline at end of file
diff --git a/AnnotationTools/ProjectAnnotations/mLibInclude.h b/AnnotationTools/ProjectAnnotations/mLibInclude.h
new file mode 100644
index 0000000..cd2dcf6
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/mLibInclude.h
@@ -0,0 +1,23 @@
+
+#ifndef MLIB_INCLUDE_H
+#define MLIB_INCLUDE_H
+
+//
+// mLib config options
+//
+#define MLIB_ERROR_CHECK
+#define MLIB_BOUNDS_CHECK
+
+//
+// mLib includes
+//
+
+#include "mLibCore.h"
+#include "mLibDepthCamera.h"
+#include "mLibD3D11.h"
+#include "mLibFLANN.h"
+#include "mLibFreeImage.h"
+
+using namespace ml;
+
+#endif
diff --git a/AnnotationTools/ProjectAnnotations/mLibSource.cpp b/AnnotationTools/ProjectAnnotations/mLibSource.cpp
new file mode 100644
index 0000000..c7e489e
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/mLibSource.cpp
@@ -0,0 +1,6 @@
+
+//#include "stdafx.h"
+
+#include "mLibCore.cpp"
+#include "mLibDepthCamera.cpp"
+#include "mLibD3D11.cpp"
\ No newline at end of file
diff --git a/AnnotationTools/ProjectAnnotations/main.cpp b/AnnotationTools/ProjectAnnotations/main.cpp
new file mode 100644
index 0000000..02cd509
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/main.cpp
@@ -0,0 +1,52 @@
+
+
+#include "stdafx.h"
+#include "Visualizer.h"
+#include "GlobalAppState.h"
+
+int _tmain(int argc, _TCHAR* argv[])
+{
+ Visualizer callback;
+
+ std::string fileNameDescGlobalApp = "zParametersScan.txt";
+ std::string scanDir = "";
+ if (argc == 3) { //overwrite scanDir with command line args
+ std::wstring argParam = std::wstring(argv[1]);
+ std::wstring argScanDir = std::wstring(argv[2]);
+ fileNameDescGlobalApp =std::string(argParam.begin(), argParam.end());
+ scanDir = std::string(argScanDir.begin(), argScanDir.end());
+ }
+ std::cout << VAR_NAME(fileNameDescGlobalApp) << " = " << fileNameDescGlobalApp << std::endl;
+ ParameterFile parameterFileGlobalApp(fileNameDescGlobalApp);
+ GlobalAppState::get().readMembers(parameterFileGlobalApp);
+ if (!scanDir.empty()) GlobalAppState::get().s_scanDir = scanDir;
+ GlobalAppState::get().print();
+
+ //get image size
+ unsigned int colorWidth = 0, colorHeight = 0;
+ scanDir = GlobalAppState::get().s_scanDir;
+ scanDir = util::replace(scanDir, '\\', '/');
+ if (scanDir.back() != '/') scanDir.push_back('/');
+ const std::string scanName = util::split(scanDir, "/").back();
+ const std::string metaFile = scanDir + scanName + ".txt";
+ if (util::fileExists(metaFile)) {
+ ParameterFile pf(metaFile);
+ if (!pf.readParameter("colorWidth", colorWidth)) {
+ std::cerr << "ERROR: failed to read \"colorWidth\" param from " << metaFile << std::endl;
+ return -1;
+ };
+ if (!pf.readParameter("colorHeight", colorHeight)) {
+ std::cerr << "ERROR: failed to read \"colorHeight\" param from " << metaFile << std::endl;
+ return -1;
+ };
+ }
+ else {
+ std::cout << "ERROR: meta-file (" << metaFile << ") does not exist! " << std::endl;
+ return -1;
+ }
+
+ ApplicationWin32 app(NULL, colorWidth, colorHeight, "Project Annotations", GraphicsDeviceTypeD3D11, callback);
+ app.messageLoop();
+
+ return 0;
+}
diff --git a/AnnotationTools/ProjectAnnotations/shaders/drawAnnotations.hlsl b/AnnotationTools/ProjectAnnotations/shaders/drawAnnotations.hlsl
new file mode 100644
index 0000000..668ec45
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/shaders/drawAnnotations.hlsl
@@ -0,0 +1,32 @@
+
+cbuffer ConstantBuffer : register(b0)
+{
+ matrix worldViewProj;
+ float4 modelColor;
+}
+
+
+struct VertexShaderOutput
+{
+ float4 position : SV_POSITION;
+ nointerpolation float4 color : TEXCOORD0;
+};
+
+VertexShaderOutput vertexShaderMain(
+ float4 position : position,
+ float3 normal : normal,
+ float4 color : color,
+ float2 texCoord : texCoord)
+{
+ VertexShaderOutput output;
+ output.position = mul(position, worldViewProj);
+ output.color = color;
+ return output;
+}
+
+
+float4 pixelShaderMain(VertexShaderOutput input) : SV_Target
+{
+ //return float4(input.color.xyz, 1.0f);
+ return input.color;
+}
diff --git a/AnnotationTools/ProjectAnnotations/stdafx.cpp b/AnnotationTools/ProjectAnnotations/stdafx.cpp
new file mode 100644
index 0000000..2b648bf
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/stdafx.cpp
@@ -0,0 +1,9 @@
+// stdafx.cpp : source file that includes just the standard includes
+// VirtualScan.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+#include "mLibSource.cpp"
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
\ No newline at end of file
diff --git a/AnnotationTools/ProjectAnnotations/stdafx.h b/AnnotationTools/ProjectAnnotations/stdafx.h
new file mode 100644
index 0000000..e494934
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/stdafx.h
@@ -0,0 +1,15 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include
+#include
+
+
+// TODO: reference additional headers your program requires here
+#include "mLibInclude.h"
\ No newline at end of file
diff --git a/AnnotationTools/ProjectAnnotations/targetver.h b/AnnotationTools/ProjectAnnotations/targetver.h
new file mode 100644
index 0000000..87c0086
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include
diff --git a/AnnotationTools/ProjectAnnotations/zParametersScan.txt b/AnnotationTools/ProjectAnnotations/zParametersScan.txt
new file mode 100644
index 0000000..d2993b1
--- /dev/null
+++ b/AnnotationTools/ProjectAnnotations/zParametersScan.txt
@@ -0,0 +1,16 @@
+
+s_scanDir = "../../data/scans/scene0000_00/";
+s_outDir = "output/";
+s_outputDebugImages = false; //output color images for visualization
+s_labelMappingFile = "../../data/tasks/scannet-labels.combined.tsv";
+s_useHiResMesh = true; //propagate annotations to hi-res mesh before projection
+s_filterUsingOrigialDepthImage = false // remove label projections corresponding to invalid depth in original depth image
+
+
+s_frameSkip = 1;
+
+s_depthMin = 0.1f; //meters
+s_depthMax = 15.0f; //meters
+s_depthDistThresh = 0.2f; //meters
+s_propagateNormalThresh = 0.5f; //radians
+
diff --git a/AnnotationTools/Readme.md b/AnnotationTools/Readme.md
new file mode 100644
index 0000000..5d529c1
--- /dev/null
+++ b/AnnotationTools/Readme.md
@@ -0,0 +1,28 @@
+
+
+## ProjectAnnotations
+
+For an RGB-D scan, projects 3d mesh annotations into 2d frames according to the camera trajectory of the sequence.
+See the parameter file `zParametersScan.txt` for input arguments.
+
+### Installation
+The code was developed under VS2013.
+
+Requirements:
+- DirectX SDK June 2010
+- our research library mLib, a git submodule in ../external/mLib
+- mLib external libraries can be downloaded [here](https://www.dropbox.com/s/fve3uen5mzonidx/mLibExternal.zip?dl=0)
+
+
+## Filter2dAnnotations
+
+Perform some basic image filtering on the raw annotation projections from `ProjectAnnotations`.
+Fill in the input paths accordingly in the main file under 'Fill in the paths accordingly here'.
+
+### Installation
+The code was developed under VS2013.
+
+Requirements:
+- NVIDIA CUDA 8.0
+- our research library mLib, a git submodule in ../external/mLib
+- mLib external libraries can be downloaded [here](https://www.dropbox.com/s/fve3uen5mzonidx/mLibExternal.zip?dl=0)
diff --git a/AnnotationTools/common/Aggregation.cpp b/AnnotationTools/common/Aggregation.cpp
new file mode 100644
index 0000000..bffa49a
--- /dev/null
+++ b/AnnotationTools/common/Aggregation.cpp
@@ -0,0 +1,3 @@
+#pragma once
+#include "stdafx.h"
+#include "Aggregation.h"
diff --git a/AnnotationTools/common/Aggregation.h b/AnnotationTools/common/Aggregation.h
new file mode 100644
index 0000000..08d0cb8
--- /dev/null
+++ b/AnnotationTools/common/Aggregation.h
@@ -0,0 +1,132 @@
+#pragma once
+#include "json.h"
+
+
+class Aggregation {
+ friend class Annotations;
+public:
+ Aggregation() {}
+ Aggregation(const std::string& sceneId, const std::string& appId,
+ const std::vector>& aggregatedSegments,
+ const std::vector>& aggregatedSegmentLabels,
+ const std::vector& objectIds) :
+ m_sceneId(sceneId), m_appId(appId),
+ m_aggregatedSegments(aggregatedSegments),
+ m_aggregatedSegmentLabels(aggregatedSegmentLabels),
+ m_objectIds(objectIds) {}
+ ~Aggregation() {}
+
+ bool empty() const { return m_aggregatedSegments.empty(); }
+ size_t size() const { return m_aggregatedSegments.size(); }
+ void clear() {
+ m_sceneId = "";
+ m_aggregatedSegments.clear();
+ m_aggregatedAnnotationIds.clear();
+ m_aggregatedSegmentLabels.clear();
+ }
+ bool empty(unsigned int i) const { return m_aggregatedSegments[i].empty(); }
+
+ std::string getSceneId() const { return m_sceneId; }
+ const std::vector>& getAggregatedSegments() const { return m_aggregatedSegments; }
+ const std::vector& getObjectIds() const { return m_objectIds; }
+ const std::unordered_map& getObjectIdsToLabels() const { return m_objectIdsToLabels; }
+ const std::vector>& getAggregatedSegmentLabels() const { return m_aggregatedSegmentLabels; }
+
+ std::unordered_map getSegIdToAggregatedSegId() const {
+ std::unordered_map mapping;
+ for (unsigned int aggid = 0; aggid < m_aggregatedSegments.size(); aggid++) {
+ const auto& agg = m_aggregatedSegments[aggid];
+ for (unsigned int segid : agg) mapping[segid] = aggid;
+ }
+ return mapping;
+ }
+
+ void setSceneId(const std::string& sceneId) { m_sceneId = sceneId; }
+
+
+ void loadFromJSONFile(const std::string& filename) {
+ if (!util::fileExists(filename)) throw MLIB_EXCEPTION("failed to open file " + filename);
+ rapidjson::Document aggregationData;
+ if (!json::parseRapidJSONDocument(filename, &aggregationData)) {
+ std::cerr << "Parse error reading " << filename << std::endl
+ << "Error code " << aggregationData.GetParseError() << " at " << aggregationData.GetErrorOffset() << std::endl;
+ return;
+ }
+ //meta-info
+ m_sceneId = aggregationData["sceneId"].GetString();
+ m_appId = aggregationData["appId"].GetString();
+
+ //segment groups
+ const auto& segGroups = aggregationData["segGroups"];
+ m_aggregatedSegments.resize(segGroups.Size());
+ m_aggregatedSegmentLabels.resize(segGroups.Size());
+ m_objectIds.resize(segGroups.Size());
+ for (unsigned int i = 0; i < segGroups.Size(); i++) {
+ const auto& group = segGroups[i];
+ unsigned int id = getUINT(group["id"]);
+ std::string label = group["label"].GetString();
+ const auto& segs = group["segments"];
+ std::vector segments(segs.Size());
+ for (unsigned int s = 0; s < segs.Size(); s++) {
+ segments[s] = getUINT(segs[s]);
+ }//segment ids (-> segmentation file)
+ m_aggregatedSegments[i].insert(segments.begin(), segments.end());
+ m_aggregatedSegmentLabels[i] = std::vector(1, label);
+ m_objectIdsToLabels[id] = label;
+ m_objectIds[i] = id;
+ }
+ }
+ void saveToJSONFile(const std::string& filename, const std::string& segFileSuffix = "_vh_clean_2.0.010000.segs.json") const {
+ using namespace json;
+ const bool endlines = true;
+
+ std::ofstream ofs(filename);
+ if (!ofs.good()) throw MLIB_EXCEPTION("failed to open " + filename + " for writing");
+ const std::function sep = put(ofs, ",", endlines);
+ const auto key = [](const std::string& id) { return "\"" + id + "\": "; };
+ ofs << "{"; if (endlines) { ofs << std::endl; }
+ ofs << key("sceneId"); toJSON(ofs, m_sceneId); sep();
+ ofs << key("appId"); toJSON(ofs, m_appId); sep();
+ ofs << key("segGroups"); ofs << "["; if (endlines) { ofs << std::endl; }
+ for (unsigned int i = 0; i < m_aggregatedSegments.size(); i++) { //each aggregated segment
+ std::vector aggregatedSegments(m_aggregatedSegments[i].begin(), m_aggregatedSegments[i].end()); //convert unordered_set to vector for json
+ //write
+ ofs << "\t{"; if (endlines) ofs << std::endl;
+ ofs << "\t" << key("id"); toJSON(ofs, m_objectIds[i]); sep();
+ ofs << "\t" << key("objectId"); toJSON(ofs, i); sep();
+ ofs << "\t" << key("segments"); toJSON(ofs, aggregatedSegments); sep();
+ ofs << "\t" << key("label"); toJSON(ofs, util::replace(m_aggregatedSegmentLabels[i].front(), "\\", "\\\\"));
+ if (endlines) ofs << std::endl;
+ ofs << "\t}";
+ if (i + 1 < m_aggregatedSegments.size()) sep();
+ }
+ if (endlines) { ofs << std::endl; }
+ ofs << "]"; sep(); //end segGroups
+ ofs << key("segmentsFile"); toJSON(ofs, m_sceneId + segFileSuffix);
+ ofs << "}"; if (endlines) { ofs << std::endl; }
+ ofs.close();
+ }
+private:
+ template
+ unsigned int getUINT(const rapidjson::GenericValue& d) const {
+ unsigned int res = (unsigned int)-1;
+ if (d.IsInt()) res = (unsigned int)d.GetInt();
+ else if (d.IsString()) res = util::convertTo(d.GetString());
+ else if (d.IsNull()) return res; //TODO HACK
+ else throw MLIB_EXCEPTION("invalid json type for uint!");
+ return res;
+ }
+
+ std::string m_sceneId;
+ std::string m_appId;
+
+ std::vector> m_aggregatedSegments; //vector of segment ids corresponding to an object
+ std::vector m_objectIds;
+
+ std::vector> m_aggregatedSegmentLabels; //vector of text labels (e.g., "table", "microwave") corresponding to above
+
+ //--not saved out in file below
+ std::vector> m_aggregatedAnnotationIds; //indexes to std::vector m_annotations;
+ std::unordered_map m_objectIdsToLabels;
+};
+
diff --git a/AnnotationTools/common/Segmentation.cpp b/AnnotationTools/common/Segmentation.cpp
new file mode 100644
index 0000000..8affcfb
--- /dev/null
+++ b/AnnotationTools/common/Segmentation.cpp
@@ -0,0 +1,15 @@
+#pragma once
+#include "stdafx.h"
+#include "Segmentation.h"
+
+Segmentation::Segmentation(const std::vector& ids, const std::string& sceneId /*= ""*/)
+{
+ clear();
+ m_sceneName = sceneId;
+ m_segmentIds = ids;
+ for (unsigned int i = 0; i < m_segmentIds.size(); i++) {
+ auto it = m_segIdsToVertIds.find(m_segmentIds[i]);
+ if (it == m_segIdsToVertIds.end()) m_segIdsToVertIds[m_segmentIds[i]] = std::vector(1, i);
+ else it->second.push_back(i);
+ }
+}
diff --git a/AnnotationTools/common/Segmentation.h b/AnnotationTools/common/Segmentation.h
new file mode 100644
index 0000000..a2e8ced
--- /dev/null
+++ b/AnnotationTools/common/Segmentation.h
@@ -0,0 +1,191 @@
+#pragma once
+#include "json.h"
+
+
+struct SegmentationParams {
+ float kThresh;
+ unsigned int segMinVerts;
+ unsigned int minPoints;
+ unsigned int maxPoints;
+ float thinThresh;
+ float flatThresh;
+ float minLength;
+ float maxLength;
+
+ SegmentationParams() {
+ kThresh = 0.0f;
+ segMinVerts = 0;
+ minPoints = 0;
+ maxPoints = 0;
+ thinThresh = 0.0f;
+ flatThresh = 0.0f;
+ minLength = 0.0f;
+ maxLength = 0.0f;
+ }
+
+ std::ostream& toJSON(std::ostream& os) const {
+ os << "{" << std::endl;
+ os << "\t\"kThresh\": \"" << kThresh << "\"," << std::endl;
+ os << "\t\"segMinVerts\": \"" << segMinVerts << "\"," << std::endl;
+ os << "\t\"minPoints\": \"" << minPoints << "\"," << std::endl;
+ os << "\t\"maxPoints\": \"" << maxPoints << "\"," << std::endl;
+ os << "\t\"thinThresh\": \"" << thinThresh << "\"," << std::endl;
+ os << "\t\"flatThresh\": \"" << flatThresh << "\"," << std::endl;
+ os << "\t\"minLength\": \"" << minLength << "\"," << std::endl;
+ os << "\t\"maxLength\": \"" << maxLength << "\"" << std::endl;
+ os << "}" << std::endl;
+ return os;
+ }
+};
+
+class Segmentation {
+public:
+ Segmentation() {}
+ Segmentation(const std::string& filename) { loadFromFile(filename); }
+ Segmentation(const std::vector& ids, const std::string& sceneId = "");
+ ~Segmentation() {}
+
+ void setSceneId(const std::string& sceneId) { m_sceneName = sceneId; }
+ void copyParamsFrom(const Segmentation& other) {
+ m_params = other.m_params;
+ }
+
+ void loadFromFile(const std::string& filename)
+ {
+ if (!ml::util::fileExists(filename)) throw MLIB_EXCEPTION("[parse] failed to open file " + filename);
+ clear();
+
+ // Parse JSON document
+ rapidjson::Document d;
+ if (!json::parseRapidJSONDocument(filename, &d)) {
+ std::cerr << "Parse error reading " << filename << std::endl
+ << "Error code " << d.GetParseError() << " at " << d.GetErrorOffset() << std::endl;
+ return;
+ }
+
+ m_sceneName = d["sceneId"].GetString();
+
+ const auto& segIndices = d["segIndices"];
+ m_segmentIds.resize(segIndices.Size());
+ for (unsigned int i = 0; i < m_segmentIds.size(); i++) {
+ m_segmentIds[i] = getUINT(segIndices[i]);
+ auto it = m_segIdsToVertIds.find(m_segmentIds[i]);
+ if (it == m_segIdsToVertIds.end()) m_segIdsToVertIds[m_segmentIds[i]] = std::vector(1, i);
+ else it->second.push_back(i);
+ }
+
+ if (d.HasMember("params")) {
+ const auto& params = d["params"];
+ m_params.kThresh = params.HasMember("kThresh") ? getFloat(params["kThresh"]) : 0.0f;
+ m_params.segMinVerts = params.HasMember("segMinVerts") ? getUINT(params["segMinVerts"]) : 0.0f;
+ m_params.minPoints = params.HasMember("minPoints") ? getUINT(params["minPoints"]) : 0.0f;
+ m_params.maxPoints = params.HasMember("maxPoints") ? getUINT(params["maxPoints"]) : 0.0f;
+ m_params.thinThresh = params.HasMember("thinThresh") ? getFloat(params["thinThresh"]) : 0.0f;
+ m_params.flatThresh = params.HasMember("flatThresh") ? getFloat(params["flatThresh"]) : 0.0f;
+ m_params.minLength = params.HasMember("minLength") ? getFloat(params["minLength"]) : 0.0f;
+ m_params.maxLength = params.HasMember("maxLength") ? getFloat(params["maxLength"]) : 0.0f;
+ }
+ }
+
+ void saveToFile(const std::string& filename)
+ {
+ std::ofstream ofs(filename);
+ const auto key = [](const std::string& id) { return "\"" + id + "\": "; };
+ ofs << "{" << std::endl;
+ ofs << key("params"); m_params.toJSON(ofs); ofs << "," << std::endl;
+ ofs << key("sceneId"); ofs << "\"" << m_sceneName << "\"," << std::endl;
+ ofs << key("segIndices"); ofs << "[";
+ for (unsigned int i = 0; i < m_segmentIds.size(); i++) {
+ ofs << m_segmentIds[i];
+ if (i + 1 < m_segmentIds.size()) ofs << ",";
+ }
+ ofs << "]" << std::endl;
+ ofs << "}" << std::endl;
+ ofs.close();
+ }
+
+ const std::vector& getSegmentIdsPerVertex() const { return m_segmentIds; }
+ size_t getNumSegments() const { return m_segIdsToVertIds.size(); }
+ const std::unordered_map>& getSegmentIdToVertIdMap() const { return m_segIdsToVertIds; }
+
+ bool empty() const { return m_segmentIds.empty(); }
+
+ void computeSurfaceAreaPerSegment(const TriMeshf& triMesh, std::unordered_map& segIdToSurfaceArea) const {
+ segIdToSurfaceArea.clear();
+ std::unordered_map> vertIdsToFaceIds;
+ for (unsigned int i = 0; i < triMesh.m_indices.size(); i++) {
+ const auto& ind = triMesh.m_indices[i];
+ for (unsigned int k = 0; k < 3; k++) {
+ auto it = vertIdsToFaceIds.find(ind[k]);
+ if (it == vertIdsToFaceIds.end()) vertIdsToFaceIds[ind[k]] = std::vector(1, i);
+ else it->second.push_back(i);
+ }
+ }
+ for (const auto& s : m_segIdsToVertIds) {
+ std::unordered_map faces; //
+ for (unsigned int vertid : s.second) {
+ const auto itf = vertIdsToFaceIds.find(vertid);
+ MLIB_ASSERT(itf != vertIdsToFaceIds.end());
+ for (unsigned int fid : itf->second) {
+ auto it = faces.find(fid);
+ if (it == faces.end()) faces[fid] = 1;
+ else it->second++;
+ }
+ }
+ //compute sa
+ float segmentSA = 0.0f;
+ for (const auto& f : faces) {
+ if (f.second == 3) {
+ const auto& ind = triMesh.m_indices[f.first];
+ Trianglef tri(triMesh.m_vertices[ind.x].position, triMesh.m_vertices[ind.y].position, triMesh.m_vertices[ind.z].position);
+ segmentSA += tri.getArea();
+ }
+ }
+ MLIB_ASSERT(segmentSA > 0.0f);
+ segIdToSurfaceArea[s.first] = segmentSA;
+ }
+ }
+
+private:
+ void clear() {
+ m_segmentIds.clear();
+ m_sceneName = "";
+ m_segIdsToVertIds.clear();
+ }
+
+ //TODO WTF IS THIS NECESSARY
+ template
+ unsigned int getUINT(const rapidjson::GenericValue& d) const {
+ unsigned int res = (unsigned int)-1;
+ if (d.IsInt()) res = (unsigned int)d.GetInt();
+ else if (d.IsUint()) res = d.GetUint();
+ else if (d.IsString()) res = util::convertTo(d.GetString());
+ else if (d.IsNull()) return res; //TODO HACK
+ else {
+ auto t = d.GetType();
+ const bool b0 = d.IsDouble();
+ const bool b1 = d.IsInt();
+ const bool b2 = d.IsInt64();
+ const bool b3 = d.IsUint();
+ const bool b4 = d.IsUint64();
+ throw MLIB_EXCEPTION("invalid json type for uint!");
+ }
+ return res;
+ }
+ template
+ float getFloat(const rapidjson::GenericValue& d) const {
+ float res = -std::numeric_limits::infinity();
+ if (d.IsDouble()) res = (float)d.GetDouble();
+ else if (d.IsInt()) res = (float)d.GetInt();
+ else if (d.IsString()) res = util::convertTo(d.GetString());
+ else throw MLIB_EXCEPTION("invalid json type for float!");
+ return res;
+ }
+
+ std::vector m_segmentIds; //correspond to vertices (indexed by vertex id)
+ std::string m_sceneName;
+
+ std::unordered_map> m_segIdsToVertIds;
+
+ SegmentationParams m_params;
+};
diff --git a/AnnotationTools/common/json.cpp b/AnnotationTools/common/json.cpp
new file mode 100644
index 0000000..36e114a
--- /dev/null
+++ b/AnnotationTools/common/json.cpp
@@ -0,0 +1,63 @@
+#include "stdafx.h"
+
+#include "json.h"
+
+#include
+
+//#include "io/io.h"
+
+namespace json {
+
+//! Wrapper around istream for parsing with rapidjson
+class istreamwrapper {
+ public:
+ typedef char Ch;
+ istreamwrapper(std::istream& is) : is_(is) { } // NOLINT
+ Ch Peek() const {
+ int c = is_.peek();
+ return c == std::char_traits::eof() ? '\0' : (Ch)c;
+ }
+ Ch Take() {
+ int c = is_.get();
+ return c == std::char_traits::eof() ? '\0' : (Ch)c;
+ }
+ size_t Tell() const { return (size_t)is_.tellg(); }
+ Ch* PutBegin() { return 0; }
+ void Put(Ch) { }
+ void Flush() { }
+ size_t PutEnd(Ch* c) { return 0; }
+ private:
+ istreamwrapper(const istreamwrapper&);
+ istreamwrapper& operator=(const istreamwrapper&);
+ std::istream& is_;
+};
+
+bool parseRapidJSONDocument(const std::string& file, rapidjson::Document* d) {
+ FILE* pFile = fopen(file.c_str(), "rb");
+ char buffer[65536];
+ rapidjson::FileReadStream is(pFile, buffer, sizeof(buffer));
+ d->ParseStream<0, rapidjson::UTF8<>, rapidjson::FileReadStream>(is);
+ fclose(pFile);
+
+ if (d->HasParseError()) {
+ std::cerr << "Parse error reading " << file << std::endl
+ << "Error code " << d->GetParseError() << " at " << d->GetErrorOffset() << std::endl;
+ return false;
+ } else {
+ return true;
+ }
+}
+
+bool parseRapidJSONString(const std::string& jsonString, rapidjson::Document* d) {
+ d->Parse(jsonString.c_str());
+
+ if (d->HasParseError()) {
+ std::cerr << "Parse error parsing json string " << std::endl
+ << "Error code " << d->GetParseError() << " at " << d->GetErrorOffset() << std::endl;
+ return false;
+ } else {
+ return true;
+ }
+}
+
+} // namespace json
diff --git a/AnnotationTools/common/json.h b/AnnotationTools/common/json.h
new file mode 100644
index 0000000..2cedaa4
--- /dev/null
+++ b/AnnotationTools/common/json.h
@@ -0,0 +1,158 @@
+#pragma once
+
+#include
+
+#define RAPIDJSON_NO_INT64DEFINE
+#include
+#include
+
+
+//#include "io/io.h"
+
+namespace json {
+
+//! Parse JSON file into rapidjson Document object d and return whether successful
+bool parseRapidJSONDocument(const std::string& file, rapidjson::Document* d);
+
+//! Parse JSON string into rapidjson Document object d and return whether successful
+bool parseRapidJSONString(const std::string& jsonString, rapidjson::Document* d);
+
+template
+void toVector(const GV& arr, std::vector* vec,
+ const std::function& conv) {
+ const unsigned n = arr.Size();
+ vec->resize(n);
+ for (unsigned i = 0; i < n; i++) {
+ (*vec)[i] = conv(arr[i]);
+ }
+}
+
+template
+void toIntVector(const GV& value, std::vector* vec) {
+ const auto conv = [](const GV& x) {
+ return x.GetInt();
+ };
+ toVector(value, vec, conv);
+}
+
+template
+void toFloatVector(const GV& value, std::vector* vec) {
+ const auto conv = [](const GV& x) {
+ return static_cast(x.GetDouble());
+ };
+ toVector(value, vec, conv);
+}
+
+template
+void toDoubleVector(const GV& value, std::vector* vec) {
+ const auto conv = [](const GV& x) {
+ return x.GetDouble();
+ };
+ toVector(value, vec, conv);
+}
+
+////! Generic toJSON function to output array-like types (should work for any type
+////! on which std::begin and std::end can work. Recurses down to basic types which
+////! are then streamed out with regular call to operator<<
+//template
+//std::ostream& toJSON(std::ostream& os, const T& x) {
+// const bool isFundamental = !std::is_arr::value;
+// if (isFundamental) {
+// return os << x;
+// }
+//
+// const auto start = std::begin(x);
+// const auto end = std::end(x) - 1;
+// os << "[";
+// for (auto it = start; it != end; it++) {
+// toJSON(os, *it); os << ",";
+// }
+// toJSON(os, *end); os << "]";
+//
+// return os;
+//}
+
+template
+std::ostream& toJSON(std::ostream& os, const T* x, size_t size) {
+ os << "[";
+ if (size == 0) { return os << "]"; }
+ const size_t iLast = size - 1;
+ for (size_t i = 0; i < iLast; i++) {
+ toJSON(os, x[i]) << ",";
+ }
+ return toJSON(os, x[iLast]) << "]";
+}
+
+template
+std::ostream& toJSON(std::ostream& os, const std::vector& x) {
+ os << "[";
+ if (x.empty()) { return os << "]"; }
+ const size_t iLast = x.size() - 1;
+ for (size_t i = 0; i < iLast; i++) {
+ toJSON(os, x[i]) << ",";
+ }
+ return toJSON(os, x[iLast]) << "]";
+}
+
+template
+std::ostream& toJSON(std::ostream& os, const std::vector& x, const std::function extractFun) {
+ os << "[";
+ if (x.empty()) { return os << "]"; }
+ const size_t iLast = x.size() - 1;
+ for (size_t i = 0; i < iLast; i++) {
+ toJSON(os, extractFun(x[i])) << ",";
+ }
+ return toJSON(os, extractFun(x[iLast])) << "]";
+}
+
+template
+std::ostream& toJSON(std::ostream& os, const std::pair& p) {
+ os << "[";
+ toJSON(os, p.first);
+ os << ",";
+ toJSON(os, p.second);
+ os << "]";
+ return os;
+}
+
+inline std::ostream& toJSON(std::ostream& os, const ml::vec2f& x) {
+ return os << "[" << x[0] << "," << x[1] << "]";
+}
+
+inline std::ostream& toJSON(std::ostream& os, const ml::vec3f& x) {
+ return os << "[" << x[0] << "," << x[1] << "," << x[2] << "]";
+}
+
+inline std::ostream& toJSON(std::ostream& os, const ml::vec4f& x) {
+ return os << "[" << x[0] << "," << x[1] << "," << x[2] << "," << x[3] << "]";
+}
+
+inline std::ostream& toJSON(std::ostream& os, const ml::mat4f& m) {
+ os << "[";
+ for (int i = 0; i < 15; i++) { os << m[i] << ","; }
+ return os << m[15] << "]";
+}
+
+template
+inline std::ostream& toJSON(std::ostream& os, const T& x) {
+ return os << x;
+}
+
+//! Quotes string TODO(MS): Escape any quotes inside string
+inline std::ostream& toJSON(std::ostream& os, const std::string& x) {
+ return os << "\"" << x << "\"";
+}
+
+//! Return a function that outputs string s and optionally endline into ostream os on every call
+inline std::function put(std::ostream& os, const std::string& s, bool endlines = false) {
+ return ([&os, s, endlines]() {
+ os << s;
+ if (endlines) {
+ os << std::endl;
+ }
+ });
+}
+
+} // namespace json
+
+
diff --git a/BenchmarkScripts/2d_evaluation/__init__.py b/BenchmarkScripts/2d_evaluation/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/BenchmarkScripts/2d_evaluation/addToConfusionMatrix.c b/BenchmarkScripts/2d_evaluation/addToConfusionMatrix.c
new file mode 100644
index 0000000..07a1585
--- /dev/null
+++ b/BenchmarkScripts/2d_evaluation/addToConfusionMatrix.c
@@ -0,0 +1,6780 @@
+/* Generated by Cython 0.24.1 */
+
+/* BEGIN: Cython Metadata
+{
+ "distutils": {
+ "depends": [
+ "cityscapesscripts/evaluation/addToConfusionMatrix_impl.c"
+ ]
+ },
+ "module_name": "cityscapesscripts.evaluation.addToConfusionMatrix"
+}
+END: Cython Metadata */
+
+#define PY_SSIZE_T_CLEAN
+#include "Python.h"
+#ifndef Py_PYTHON_H
+ #error Python headers needed to compile C extensions, please install development version of Python.
+#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03020000)
+ #error Cython requires Python 2.6+ or Python 3.2+.
+#else
+#define CYTHON_ABI "0_24_1"
+#include
+#ifndef offsetof
+ #define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
+#endif
+#if !defined(WIN32) && !defined(MS_WINDOWS)
+ #ifndef __stdcall
+ #define __stdcall
+ #endif
+ #ifndef __cdecl
+ #define __cdecl
+ #endif
+ #ifndef __fastcall
+ #define __fastcall
+ #endif
+#endif
+#ifndef DL_IMPORT
+ #define DL_IMPORT(t) t
+#endif
+#ifndef DL_EXPORT
+ #define DL_EXPORT(t) t
+#endif
+#ifndef PY_LONG_LONG
+ #define PY_LONG_LONG LONG_LONG
+#endif
+#ifndef Py_HUGE_VAL
+ #define Py_HUGE_VAL HUGE_VAL
+#endif
+#ifdef PYPY_VERSION
+ #define CYTHON_COMPILING_IN_PYPY 1
+ #define CYTHON_COMPILING_IN_CPYTHON 0
+#else
+ #define CYTHON_COMPILING_IN_PYPY 0
+ #define CYTHON_COMPILING_IN_CPYTHON 1
+#endif
+#if !defined(CYTHON_USE_PYLONG_INTERNALS) && CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x02070000
+ #define CYTHON_USE_PYLONG_INTERNALS 1
+#endif
+#if CYTHON_USE_PYLONG_INTERNALS
+ #include "longintrepr.h"
+ #undef SHIFT
+ #undef BASE
+ #undef MASK
+#endif
+#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag)
+ #define Py_OptimizeFlag 0
+#endif
+#define __PYX_BUILD_PY_SSIZE_T "n"
+#define CYTHON_FORMAT_SSIZE_T "z"
+#if PY_MAJOR_VERSION < 3
+ #define __Pyx_BUILTIN_MODULE_NAME "__builtin__"
+ #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\
+ PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
+ #define __Pyx_DefaultClassType PyClass_Type
+#else
+ #define __Pyx_BUILTIN_MODULE_NAME "builtins"
+ #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\
+ PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
+ #define __Pyx_DefaultClassType PyType_Type
+#endif
+#ifndef Py_TPFLAGS_CHECKTYPES
+ #define Py_TPFLAGS_CHECKTYPES 0
+#endif
+#ifndef Py_TPFLAGS_HAVE_INDEX
+ #define Py_TPFLAGS_HAVE_INDEX 0
+#endif
+#ifndef Py_TPFLAGS_HAVE_NEWBUFFER
+ #define Py_TPFLAGS_HAVE_NEWBUFFER 0
+#endif
+#ifndef Py_TPFLAGS_HAVE_FINALIZE
+ #define Py_TPFLAGS_HAVE_FINALIZE 0
+#endif
+#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND)
+ #define CYTHON_PEP393_ENABLED 1
+ #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\
+ 0 : _PyUnicode_Ready((PyObject *)(op)))
+ #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u)
+ #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i)
+ #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u)
+ #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u)
+ #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i)
+ #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u)))
+#else
+ #define CYTHON_PEP393_ENABLED 0
+ #define __Pyx_PyUnicode_READY(op) (0)
+ #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u)
+ #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i]))
+ #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE))
+ #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u))
+ #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i]))
+ #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u))
+#endif
+#if CYTHON_COMPILING_IN_PYPY
+ #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b)
+ #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b)
+#else
+ #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b)
+ #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\
+ PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b))
+#endif
+#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains)
+ #define PyUnicode_Contains(u, s) PySequence_Contains(u, s)
+#endif
+#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check)
+ #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type)
+#endif
+#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format)
+ #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt)
+#endif
+#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc)
+ #define PyObject_Malloc(s) PyMem_Malloc(s)
+ #define PyObject_Free(p) PyMem_Free(p)
+ #define PyObject_Realloc(p) PyMem_Realloc(p)
+#endif
+#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b))
+#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b))
+#if PY_MAJOR_VERSION >= 3
+ #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b)
+#else
+ #define __Pyx_PyString_Format(a, b) PyString_Format(a, b)
+#endif
+#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII)
+ #define PyObject_ASCII(o) PyObject_Repr(o)
+#endif
+#if PY_MAJOR_VERSION >= 3
+ #define PyBaseString_Type PyUnicode_Type
+ #define PyStringObject PyUnicodeObject
+ #define PyString_Type PyUnicode_Type
+ #define PyString_Check PyUnicode_Check
+ #define PyString_CheckExact PyUnicode_CheckExact
+#endif
+#if PY_MAJOR_VERSION >= 3
+ #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj)
+ #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj)
+#else
+ #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj))
+ #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj))
+#endif
+#ifndef PySet_CheckExact
+ #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type)
+#endif
+#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
+#if PY_MAJOR_VERSION >= 3
+ #define PyIntObject PyLongObject
+ #define PyInt_Type PyLong_Type
+ #define PyInt_Check(op) PyLong_Check(op)
+ #define PyInt_CheckExact(op) PyLong_CheckExact(op)
+ #define PyInt_FromString PyLong_FromString
+ #define PyInt_FromUnicode PyLong_FromUnicode
+ #define PyInt_FromLong PyLong_FromLong
+ #define PyInt_FromSize_t PyLong_FromSize_t
+ #define PyInt_FromSsize_t PyLong_FromSsize_t
+ #define PyInt_AsLong PyLong_AsLong
+ #define PyInt_AS_LONG PyLong_AS_LONG
+ #define PyInt_AsSsize_t PyLong_AsSsize_t
+ #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask
+ #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask
+ #define PyNumber_Int PyNumber_Long
+#endif
+#if PY_MAJOR_VERSION >= 3
+ #define PyBoolObject PyLongObject
+#endif
+#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY
+ #ifndef PyUnicode_InternFromString
+ #define PyUnicode_InternFromString(s) PyUnicode_FromString(s)
+ #endif
+#endif
+#if PY_VERSION_HEX < 0x030200A4
+ typedef long Py_hash_t;
+ #define __Pyx_PyInt_FromHash_t PyInt_FromLong
+ #define __Pyx_PyInt_AsHash_t PyInt_AsLong
+#else
+ #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t
+ #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t
+#endif
+#if PY_MAJOR_VERSION >= 3
+ #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : PyInstanceMethod_New(func))
+#else
+ #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass)
+#endif
+#if PY_VERSION_HEX >= 0x030500B1
+#define __Pyx_PyAsyncMethodsStruct PyAsyncMethods
+#define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async)
+#elif CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+typedef struct {
+ unaryfunc am_await;
+ unaryfunc am_aiter;
+ unaryfunc am_anext;
+} __Pyx_PyAsyncMethodsStruct;
+#define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved))
+#else
+#define __Pyx_PyType_AsAsync(obj) NULL
+#endif
+#ifndef CYTHON_RESTRICT
+ #if defined(__GNUC__)
+ #define CYTHON_RESTRICT __restrict__
+ #elif defined(_MSC_VER) && _MSC_VER >= 1400
+ #define CYTHON_RESTRICT __restrict
+ #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+ #define CYTHON_RESTRICT restrict
+ #else
+ #define CYTHON_RESTRICT
+ #endif
+#endif
+#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None)
+
+#ifndef CYTHON_INLINE
+ #if defined(__GNUC__)
+ #define CYTHON_INLINE __inline__
+ #elif defined(_MSC_VER)
+ #define CYTHON_INLINE __inline
+ #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+ #define CYTHON_INLINE inline
+ #else
+ #define CYTHON_INLINE
+ #endif
+#endif
+
+#if defined(WIN32) || defined(MS_WINDOWS)
+ #define _USE_MATH_DEFINES
+#endif
+#include
+#ifdef NAN
+#define __PYX_NAN() ((float) NAN)
+#else
+static CYTHON_INLINE float __PYX_NAN() {
+ float value;
+ memset(&value, 0xFF, sizeof(value));
+ return value;
+}
+#endif
+#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL)
+#define __Pyx_truncl trunc
+#else
+#define __Pyx_truncl truncl
+#endif
+
+
+#define __PYX_ERR(f_index, lineno, Ln_error) \
+{ \
+ __pyx_filename = __pyx_f[f_index]; __pyx_lineno = lineno; __pyx_clineno = __LINE__; goto Ln_error; \
+}
+
+#if PY_MAJOR_VERSION >= 3
+ #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y)
+ #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y)
+#else
+ #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y)
+ #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y)
+#endif
+
+#ifndef __PYX_EXTERN_C
+ #ifdef __cplusplus
+ #define __PYX_EXTERN_C extern "C"
+ #else
+ #define __PYX_EXTERN_C extern
+ #endif
+#endif
+
+#define __PYX_HAVE__cityscapesscripts__evaluation__addToConfusionMatrix
+#define __PYX_HAVE_API__cityscapesscripts__evaluation__addToConfusionMatrix
+#include "string.h"
+#include "stdio.h"
+#include "stdlib.h"
+#include "numpy/arrayobject.h"
+#include "numpy/ufuncobject.h"
+#include "addToConfusionMatrix_impl.c"
+#ifdef _OPENMP
+#include
+#endif /* _OPENMP */
+
+#ifdef PYREX_WITHOUT_ASSERTIONS
+#define CYTHON_WITHOUT_ASSERTIONS
+#endif
+
+#ifndef CYTHON_UNUSED
+# if defined(__GNUC__)
+# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+# define CYTHON_UNUSED __attribute__ ((__unused__))
+# else
+# define CYTHON_UNUSED
+# endif
+# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER))
+# define CYTHON_UNUSED __attribute__ ((__unused__))
+# else
+# define CYTHON_UNUSED
+# endif
+#endif
+#ifndef CYTHON_NCP_UNUSED
+# if CYTHON_COMPILING_IN_CPYTHON
+# define CYTHON_NCP_UNUSED
+# else
+# define CYTHON_NCP_UNUSED CYTHON_UNUSED
+# endif
+#endif
+typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding;
+ const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry;
+
+#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0
+#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 0
+#define __PYX_DEFAULT_STRING_ENCODING ""
+#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString
+#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
+#define __Pyx_uchar_cast(c) ((unsigned char)c)
+#define __Pyx_long_cast(x) ((long)x)
+#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\
+ (sizeof(type) < sizeof(Py_ssize_t)) ||\
+ (sizeof(type) > sizeof(Py_ssize_t) &&\
+ likely(v < (type)PY_SSIZE_T_MAX ||\
+ v == (type)PY_SSIZE_T_MAX) &&\
+ (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\
+ v == (type)PY_SSIZE_T_MIN))) ||\
+ (sizeof(type) == sizeof(Py_ssize_t) &&\
+ (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\
+ v == (type)PY_SSIZE_T_MAX))) )
+#if defined (__cplusplus) && __cplusplus >= 201103L
+ #include
+ #define __Pyx_sst_abs(value) std::abs(value)
+#elif SIZEOF_INT >= SIZEOF_SIZE_T
+ #define __Pyx_sst_abs(value) abs(value)
+#elif SIZEOF_LONG >= SIZEOF_SIZE_T
+ #define __Pyx_sst_abs(value) labs(value)
+#elif defined (_MSC_VER) && defined (_M_X64)
+ #define __Pyx_sst_abs(value) _abs64(value)
+#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+ #define __Pyx_sst_abs(value) llabs(value)
+#elif defined (__GNUC__)
+ #define __Pyx_sst_abs(value) __builtin_llabs(value)
+#else
+ #define __Pyx_sst_abs(value) ((value<0) ? -value : value)
+#endif
+static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject*);
+static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length);
+#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s))
+#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l)
+#define __Pyx_PyBytes_FromString PyBytes_FromString
+#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize
+static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*);
+#if PY_MAJOR_VERSION < 3
+ #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString
+ #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
+#else
+ #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString
+ #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize
+#endif
+#define __Pyx_PyObject_AsSString(s) ((signed char*) __Pyx_PyObject_AsString(s))
+#define __Pyx_PyObject_AsUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s))
+#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s)
+#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s)
+#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s)
+#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s)
+#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s)
+#if PY_MAJOR_VERSION < 3
+static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u)
+{
+ const Py_UNICODE *u_end = u;
+ while (*u_end++) ;
+ return (size_t)(u_end - u - 1);
+}
+#else
+#define __Pyx_Py_UNICODE_strlen Py_UNICODE_strlen
+#endif
+#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u))
+#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode
+#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode
+#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj)
+#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None)
+#define __Pyx_PyBool_FromLong(b) ((b) ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False))
+static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
+static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x);
+static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*);
+static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
+#if CYTHON_COMPILING_IN_CPYTHON
+#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
+#else
+#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x)
+#endif
+#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x))
+#if PY_MAJOR_VERSION >= 3
+#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x))
+#else
+#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x))
+#endif
+#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x))
+#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
+static int __Pyx_sys_getdefaultencoding_not_ascii;
+static int __Pyx_init_sys_getdefaultencoding_params(void) {
+ PyObject* sys;
+ PyObject* default_encoding = NULL;
+ PyObject* ascii_chars_u = NULL;
+ PyObject* ascii_chars_b = NULL;
+ const char* default_encoding_c;
+ sys = PyImport_ImportModule("sys");
+ if (!sys) goto bad;
+ default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL);
+ Py_DECREF(sys);
+ if (!default_encoding) goto bad;
+ default_encoding_c = PyBytes_AsString(default_encoding);
+ if (!default_encoding_c) goto bad;
+ if (strcmp(default_encoding_c, "ascii") == 0) {
+ __Pyx_sys_getdefaultencoding_not_ascii = 0;
+ } else {
+ char ascii_chars[128];
+ int c;
+ for (c = 0; c < 128; c++) {
+ ascii_chars[c] = c;
+ }
+ __Pyx_sys_getdefaultencoding_not_ascii = 1;
+ ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL);
+ if (!ascii_chars_u) goto bad;
+ ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL);
+ if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) {
+ PyErr_Format(
+ PyExc_ValueError,
+ "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.",
+ default_encoding_c);
+ goto bad;
+ }
+ Py_DECREF(ascii_chars_u);
+ Py_DECREF(ascii_chars_b);
+ }
+ Py_DECREF(default_encoding);
+ return 0;
+bad:
+ Py_XDECREF(default_encoding);
+ Py_XDECREF(ascii_chars_u);
+ Py_XDECREF(ascii_chars_b);
+ return -1;
+}
+#endif
+#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3
+#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL)
+#else
+#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL)
+#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT
+static char* __PYX_DEFAULT_STRING_ENCODING;
+static int __Pyx_init_sys_getdefaultencoding_params(void) {
+ PyObject* sys;
+ PyObject* default_encoding = NULL;
+ char* default_encoding_c;
+ sys = PyImport_ImportModule("sys");
+ if (!sys) goto bad;
+ default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL);
+ Py_DECREF(sys);
+ if (!default_encoding) goto bad;
+ default_encoding_c = PyBytes_AsString(default_encoding);
+ if (!default_encoding_c) goto bad;
+ __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c));
+ if (!__PYX_DEFAULT_STRING_ENCODING) goto bad;
+ strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c);
+ Py_DECREF(default_encoding);
+ return 0;
+bad:
+ Py_XDECREF(default_encoding);
+ return -1;
+}
+#endif
+#endif
+
+
+/* Test for GCC > 2.95 */
+#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))
+ #define likely(x) __builtin_expect(!!(x), 1)
+ #define unlikely(x) __builtin_expect(!!(x), 0)
+#else /* !__GNUC__ or GCC < 2.95 */
+ #define likely(x) (x)
+ #define unlikely(x) (x)
+#endif /* __GNUC__ */
+
+static PyObject *__pyx_m;
+static PyObject *__pyx_d;
+static PyObject *__pyx_b;
+static PyObject *__pyx_empty_tuple;
+static PyObject *__pyx_empty_bytes;
+static PyObject *__pyx_empty_unicode;
+static int __pyx_lineno;
+static int __pyx_clineno = 0;
+static const char * __pyx_cfilenm= __FILE__;
+static const char *__pyx_filename;
+
+/* None.proto */
+#if !defined(CYTHON_CCOMPLEX)
+ #if defined(__cplusplus)
+ #define CYTHON_CCOMPLEX 1
+ #elif defined(_Complex_I)
+ #define CYTHON_CCOMPLEX 1
+ #else
+ #define CYTHON_CCOMPLEX 0
+ #endif
+#endif
+#if CYTHON_CCOMPLEX
+ #ifdef __cplusplus
+ #include
+ #else
+ #include
+ #endif
+#endif
+#if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__)
+ #undef _Complex_I
+ #define _Complex_I 1.0fj
+#endif
+
+
+static const char *__pyx_f[] = {
+ "cityscapesscripts/evaluation/addToConfusionMatrix.pyx",
+ "__init__.pxd",
+ "type.pxd",
+};
+/* BufferFormatStructs.proto */
+#define IS_UNSIGNED(type) (((type) -1) > 0)
+struct __Pyx_StructField_;
+#define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0)
+typedef struct {
+ const char* name;
+ struct __Pyx_StructField_* fields;
+ size_t size;
+ size_t arraysize[8];
+ int ndim;
+ char typegroup;
+ char is_unsigned;
+ int flags;
+} __Pyx_TypeInfo;
+typedef struct __Pyx_StructField_ {
+ __Pyx_TypeInfo* type;
+ const char* name;
+ size_t offset;
+} __Pyx_StructField;
+typedef struct {
+ __Pyx_StructField* field;
+ size_t parent_offset;
+} __Pyx_BufFmt_StackElem;
+typedef struct {
+ __Pyx_StructField root;
+ __Pyx_BufFmt_StackElem* head;
+ size_t fmt_offset;
+ size_t new_count, enc_count;
+ size_t struct_alignment;
+ int is_complex;
+ char enc_type;
+ char new_packmode;
+ char enc_packmode;
+ char is_valid_array;
+} __Pyx_BufFmt_Context;
+
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":725
+ * # in Cython to enable them only on the right systems.
+ *
+ * ctypedef npy_int8 int8_t # <<<<<<<<<<<<<<
+ * ctypedef npy_int16 int16_t
+ * ctypedef npy_int32 int32_t
+ */
+typedef npy_int8 __pyx_t_5numpy_int8_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":726
+ *
+ * ctypedef npy_int8 int8_t
+ * ctypedef npy_int16 int16_t # <<<<<<<<<<<<<<
+ * ctypedef npy_int32 int32_t
+ * ctypedef npy_int64 int64_t
+ */
+typedef npy_int16 __pyx_t_5numpy_int16_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":727
+ * ctypedef npy_int8 int8_t
+ * ctypedef npy_int16 int16_t
+ * ctypedef npy_int32 int32_t # <<<<<<<<<<<<<<
+ * ctypedef npy_int64 int64_t
+ * #ctypedef npy_int96 int96_t
+ */
+typedef npy_int32 __pyx_t_5numpy_int32_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":728
+ * ctypedef npy_int16 int16_t
+ * ctypedef npy_int32 int32_t
+ * ctypedef npy_int64 int64_t # <<<<<<<<<<<<<<
+ * #ctypedef npy_int96 int96_t
+ * #ctypedef npy_int128 int128_t
+ */
+typedef npy_int64 __pyx_t_5numpy_int64_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":732
+ * #ctypedef npy_int128 int128_t
+ *
+ * ctypedef npy_uint8 uint8_t # <<<<<<<<<<<<<<
+ * ctypedef npy_uint16 uint16_t
+ * ctypedef npy_uint32 uint32_t
+ */
+typedef npy_uint8 __pyx_t_5numpy_uint8_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":733
+ *
+ * ctypedef npy_uint8 uint8_t
+ * ctypedef npy_uint16 uint16_t # <<<<<<<<<<<<<<
+ * ctypedef npy_uint32 uint32_t
+ * ctypedef npy_uint64 uint64_t
+ */
+typedef npy_uint16 __pyx_t_5numpy_uint16_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":734
+ * ctypedef npy_uint8 uint8_t
+ * ctypedef npy_uint16 uint16_t
+ * ctypedef npy_uint32 uint32_t # <<<<<<<<<<<<<<
+ * ctypedef npy_uint64 uint64_t
+ * #ctypedef npy_uint96 uint96_t
+ */
+typedef npy_uint32 __pyx_t_5numpy_uint32_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":735
+ * ctypedef npy_uint16 uint16_t
+ * ctypedef npy_uint32 uint32_t
+ * ctypedef npy_uint64 uint64_t # <<<<<<<<<<<<<<
+ * #ctypedef npy_uint96 uint96_t
+ * #ctypedef npy_uint128 uint128_t
+ */
+typedef npy_uint64 __pyx_t_5numpy_uint64_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":739
+ * #ctypedef npy_uint128 uint128_t
+ *
+ * ctypedef npy_float32 float32_t # <<<<<<<<<<<<<<
+ * ctypedef npy_float64 float64_t
+ * #ctypedef npy_float80 float80_t
+ */
+typedef npy_float32 __pyx_t_5numpy_float32_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":740
+ *
+ * ctypedef npy_float32 float32_t
+ * ctypedef npy_float64 float64_t # <<<<<<<<<<<<<<
+ * #ctypedef npy_float80 float80_t
+ * #ctypedef npy_float128 float128_t
+ */
+typedef npy_float64 __pyx_t_5numpy_float64_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":749
+ * # The int types are mapped a bit surprising --
+ * # numpy.int corresponds to 'l' and numpy.long to 'q'
+ * ctypedef npy_long int_t # <<<<<<<<<<<<<<
+ * ctypedef npy_longlong long_t
+ * ctypedef npy_longlong longlong_t
+ */
+typedef npy_long __pyx_t_5numpy_int_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":750
+ * # numpy.int corresponds to 'l' and numpy.long to 'q'
+ * ctypedef npy_long int_t
+ * ctypedef npy_longlong long_t # <<<<<<<<<<<<<<
+ * ctypedef npy_longlong longlong_t
+ *
+ */
+typedef npy_longlong __pyx_t_5numpy_long_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":751
+ * ctypedef npy_long int_t
+ * ctypedef npy_longlong long_t
+ * ctypedef npy_longlong longlong_t # <<<<<<<<<<<<<<
+ *
+ * ctypedef npy_ulong uint_t
+ */
+typedef npy_longlong __pyx_t_5numpy_longlong_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":753
+ * ctypedef npy_longlong longlong_t
+ *
+ * ctypedef npy_ulong uint_t # <<<<<<<<<<<<<<
+ * ctypedef npy_ulonglong ulong_t
+ * ctypedef npy_ulonglong ulonglong_t
+ */
+typedef npy_ulong __pyx_t_5numpy_uint_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":754
+ *
+ * ctypedef npy_ulong uint_t
+ * ctypedef npy_ulonglong ulong_t # <<<<<<<<<<<<<<
+ * ctypedef npy_ulonglong ulonglong_t
+ *
+ */
+typedef npy_ulonglong __pyx_t_5numpy_ulong_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":755
+ * ctypedef npy_ulong uint_t
+ * ctypedef npy_ulonglong ulong_t
+ * ctypedef npy_ulonglong ulonglong_t # <<<<<<<<<<<<<<
+ *
+ * ctypedef npy_intp intp_t
+ */
+typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":757
+ * ctypedef npy_ulonglong ulonglong_t
+ *
+ * ctypedef npy_intp intp_t # <<<<<<<<<<<<<<
+ * ctypedef npy_uintp uintp_t
+ *
+ */
+typedef npy_intp __pyx_t_5numpy_intp_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":758
+ *
+ * ctypedef npy_intp intp_t
+ * ctypedef npy_uintp uintp_t # <<<<<<<<<<<<<<
+ *
+ * ctypedef npy_double float_t
+ */
+typedef npy_uintp __pyx_t_5numpy_uintp_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":760
+ * ctypedef npy_uintp uintp_t
+ *
+ * ctypedef npy_double float_t # <<<<<<<<<<<<<<
+ * ctypedef npy_double double_t
+ * ctypedef npy_longdouble longdouble_t
+ */
+typedef npy_double __pyx_t_5numpy_float_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":761
+ *
+ * ctypedef npy_double float_t
+ * ctypedef npy_double double_t # <<<<<<<<<<<<<<
+ * ctypedef npy_longdouble longdouble_t
+ *
+ */
+typedef npy_double __pyx_t_5numpy_double_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":762
+ * ctypedef npy_double float_t
+ * ctypedef npy_double double_t
+ * ctypedef npy_longdouble longdouble_t # <<<<<<<<<<<<<<
+ *
+ * ctypedef npy_cfloat cfloat_t
+ */
+typedef npy_longdouble __pyx_t_5numpy_longdouble_t;
+/* None.proto */
+#if CYTHON_CCOMPLEX
+ #ifdef __cplusplus
+ typedef ::std::complex< float > __pyx_t_float_complex;
+ #else
+ typedef float _Complex __pyx_t_float_complex;
+ #endif
+#else
+ typedef struct { float real, imag; } __pyx_t_float_complex;
+#endif
+
+/* None.proto */
+#if CYTHON_CCOMPLEX
+ #ifdef __cplusplus
+ typedef ::std::complex< double > __pyx_t_double_complex;
+ #else
+ typedef double _Complex __pyx_t_double_complex;
+ #endif
+#else
+ typedef struct { double real, imag; } __pyx_t_double_complex;
+#endif
+
+
+/*--- Type declarations ---*/
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":764
+ * ctypedef npy_longdouble longdouble_t
+ *
+ * ctypedef npy_cfloat cfloat_t # <<<<<<<<<<<<<<
+ * ctypedef npy_cdouble cdouble_t
+ * ctypedef npy_clongdouble clongdouble_t
+ */
+typedef npy_cfloat __pyx_t_5numpy_cfloat_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":765
+ *
+ * ctypedef npy_cfloat cfloat_t
+ * ctypedef npy_cdouble cdouble_t # <<<<<<<<<<<<<<
+ * ctypedef npy_clongdouble clongdouble_t
+ *
+ */
+typedef npy_cdouble __pyx_t_5numpy_cdouble_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":766
+ * ctypedef npy_cfloat cfloat_t
+ * ctypedef npy_cdouble cdouble_t
+ * ctypedef npy_clongdouble clongdouble_t # <<<<<<<<<<<<<<
+ *
+ * ctypedef npy_cdouble complex_t
+ */
+typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t;
+
+/* "../../../home/hassan/anaconda2/lib/python2.7/site-packages/Cython/Includes/numpy/__init__.pxd":768
+ * ctypedef npy_clongdouble clongdouble_t
+ *
+ * ctypedef npy_cdouble complex_t # <<<<<<<<<<<<<<
+ *
+ * cdef inline object PyArray_MultiIterNew1(a):
+ */
+typedef npy_cdouble __pyx_t_5numpy_complex_t;
+
+/* --- Runtime support code (head) --- */
+/* Refnanny.proto */
+#ifndef CYTHON_REFNANNY
+ #define CYTHON_REFNANNY 0
+#endif
+#if CYTHON_REFNANNY
+ typedef struct {
+ void (*INCREF)(void*, PyObject*, int);
+ void (*DECREF)(void*, PyObject*, int);
+ void (*GOTREF)(void*, PyObject*, int);
+ void (*GIVEREF)(void*, PyObject*, int);
+ void* (*SetupContext)(const char*, int, const char*);
+ void (*FinishContext)(void**);
+ } __Pyx_RefNannyAPIStruct;
+ static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL;
+ static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname);
+ #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL;
+#ifdef WITH_THREAD
+ #define __Pyx_RefNannySetupContext(name, acquire_gil)\
+ if (acquire_gil) {\
+ PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\
+ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\
+ PyGILState_Release(__pyx_gilstate_save);\
+ } else {\
+ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\
+ }
+#else
+ #define __Pyx_RefNannySetupContext(name, acquire_gil)\
+ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
+#endif
+ #define __Pyx_RefNannyFinishContext()\
+ __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
+ #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+ #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+ #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+ #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+ #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0)
+ #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0)
+ #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0)
+ #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0)
+#else
+ #define __Pyx_RefNannyDeclarations
+ #define __Pyx_RefNannySetupContext(name, acquire_gil)
+ #define __Pyx_RefNannyFinishContext()
+ #define __Pyx_INCREF(r) Py_INCREF(r)
+ #define __Pyx_DECREF(r) Py_DECREF(r)
+ #define __Pyx_GOTREF(r)
+ #define __Pyx_GIVEREF(r)
+ #define __Pyx_XINCREF(r) Py_XINCREF(r)
+ #define __Pyx_XDECREF(r) Py_XDECREF(r)
+ #define __Pyx_XGOTREF(r)
+ #define __Pyx_XGIVEREF(r)
+#endif
+#define __Pyx_XDECREF_SET(r, v) do {\
+ PyObject *tmp = (PyObject *) r;\
+ r = v; __Pyx_XDECREF(tmp);\
+ } while (0)
+#define __Pyx_DECREF_SET(r, v) do {\
+ PyObject *tmp = (PyObject *) r;\
+ r = v; __Pyx_DECREF(tmp);\
+ } while (0)
+#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0)
+#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0)
+
+/* PyObjectGetAttrStr.proto */
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) {
+ PyTypeObject* tp = Py_TYPE(obj);
+ if (likely(tp->tp_getattro))
+ return tp->tp_getattro(obj, attr_name);
+#if PY_MAJOR_VERSION < 3
+ if (likely(tp->tp_getattr))
+ return tp->tp_getattr(obj, PyString_AS_STRING(attr_name));
+#endif
+ return PyObject_GetAttr(obj, attr_name);
+}
+#else
+#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n)
+#endif
+
+/* GetBuiltinName.proto */
+static PyObject *__Pyx_GetBuiltinName(PyObject *name);
+
+/* PyThreadStateGet.proto */
+#if CYTHON_COMPILING_IN_CPYTHON
+#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate;
+#define __Pyx_PyThreadState_assign __pyx_tstate = PyThreadState_GET();
+#else
+#define __Pyx_PyThreadState_declare
+#define __Pyx_PyThreadState_assign
+#endif
+
+/* PyErrFetchRestore.proto */
+#if CYTHON_COMPILING_IN_CPYTHON
+#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb)
+#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb)
+#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb)
+#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb)
+static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb);
+static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb);
+#else
+#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb)
+#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb)
+#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb)
+#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb)
+#endif
+
+/* RaiseException.proto */
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause);
+
+/* RaiseArgTupleInvalid.proto */
+static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
+ Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found);
+
+/* RaiseDoubleKeywords.proto */
+static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name);
+
+/* ParseKeywords.proto */
+static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\
+ PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\
+ const char* function_name);
+
+/* ArgTypeTest.proto */
+static CYTHON_INLINE int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
+ const char *name, int exact);
+
+/* BufferFormatCheck.proto */
+static CYTHON_INLINE int __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj,
+ __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
+static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info);
+static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts);
+static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
+ __Pyx_BufFmt_StackElem* stack,
+ __Pyx_TypeInfo* type); // PROTO
+
+/* GetModuleGlobalName.proto */
+static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name);
+
+/* PyObjectCall.proto */
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw);
+#else
+#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw)
+#endif
+
+/* ExtTypeTest.proto */
+static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type);
+
+/* BufferFallbackError.proto */
+static void __Pyx_RaiseBufferFallbackError(void);
+
+#define __Pyx_BufPtrCContig2d(type, buf, i0, s0, i1, s1) ((type)((char*)buf + i0 * s0) + i1)
+/* PyObjectCallMethO.proto */
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg);
+#endif
+
+/* PyObjectCallOneArg.proto */
+static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg);
+
+/* DictGetItem.proto */
+#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY
+static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) {
+ PyObject *value;
+ value = PyDict_GetItemWithError(d, key);
+ if (unlikely(!value)) {
+ if (!PyErr_Occurred()) {
+ PyObject* args = PyTuple_Pack(1, key);
+ if (likely(args))
+ PyErr_SetObject(PyExc_KeyError, args);
+ Py_XDECREF(args);
+ }
+ return NULL;
+ }
+ Py_INCREF(value);
+ return value;
+}
+#else
+ #define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key)
+#endif
+
+/* RaiseTooManyValuesToUnpack.proto */
+static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);
+
+/* RaiseNeedMoreValuesToUnpack.proto */
+static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
+
+/* RaiseNoneIterError.proto */
+static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void);
+
+/* Import.proto */
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level);
+
+/* CodeObjectCache.proto */
+typedef struct {
+ PyCodeObject* code_object;
+ int code_line;
+} __Pyx_CodeObjectCacheEntry;
+struct __Pyx_CodeObjectCache {
+ int count;
+ int max_count;
+ __Pyx_CodeObjectCacheEntry* entries;
+};
+static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL};
+static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line);
+static PyCodeObject *__pyx_find_code_object(int code_line);
+static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object);
+
+/* AddTraceback.proto */
+static void __Pyx_AddTraceback(const char *funcname, int c_line,
+ int py_line, const char *filename);
+
+/* BufferStructDeclare.proto */
+typedef struct {
+ Py_ssize_t shape, strides, suboffsets;
+} __Pyx_Buf_DimInfo;
+typedef struct {
+ size_t refcount;
+ Py_buffer pybuffer;
+} __Pyx_Buffer;
+typedef struct {
+ __Pyx_Buffer *rcbuffer;
+ char *data;
+ __Pyx_Buf_DimInfo diminfo[8];
+} __Pyx_LocalBuf_ND;
+
+#if PY_MAJOR_VERSION < 3
+ static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
+ static void __Pyx_ReleaseBuffer(Py_buffer *view);
+#else
+ #define __Pyx_GetBuffer PyObject_GetBuffer
+ #define __Pyx_ReleaseBuffer PyBuffer_Release
+#endif
+
+
+/* None.proto */
+static Py_ssize_t __Pyx_zeros[] = {0, 0, 0, 0, 0, 0, 0, 0};
+static Py_ssize_t __Pyx_minusones[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+
+/* CIntToPy.proto */
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_unsigned_PY_LONG_LONG(unsigned PY_LONG_LONG value);
+
+/* None.proto */
+#if CYTHON_CCOMPLEX
+ #ifdef __cplusplus
+ #define __Pyx_CREAL(z) ((z).real())
+ #define __Pyx_CIMAG(z) ((z).imag())
+ #else
+ #define __Pyx_CREAL(z) (__real__(z))
+ #define __Pyx_CIMAG(z) (__imag__(z))
+ #endif
+#else
+ #define __Pyx_CREAL(z) ((z).real)
+ #define __Pyx_CIMAG(z) ((z).imag)
+#endif
+#if defined(__cplusplus) && CYTHON_CCOMPLEX && (defined(_WIN32) || defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 5 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 )) || __cplusplus >= 201103)
+ #define __Pyx_SET_CREAL(z,x) ((z).real(x))
+ #define __Pyx_SET_CIMAG(z,y) ((z).imag(y))
+#else
+ #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x)
+ #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y)
+#endif
+
+/* None.proto */
+static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float, float);
+
+/* None.proto */
+#if CYTHON_CCOMPLEX
+ #define __Pyx_c_eqf(a, b) ((a)==(b))
+ #define __Pyx_c_sumf(a, b) ((a)+(b))
+ #define __Pyx_c_difff(a, b) ((a)-(b))
+ #define __Pyx_c_prodf(a, b) ((a)*(b))
+ #define __Pyx_c_quotf(a, b) ((a)/(b))
+ #define __Pyx_c_negf(a) (-(a))
+ #ifdef __cplusplus
+ #define __Pyx_c_is_zerof(z) ((z)==(float)0)
+ #define __Pyx_c_conjf(z) (::std::conj(z))
+ #if 1
+ #define __Pyx_c_absf(z) (::std::abs(z))
+ #define __Pyx_c_powf(a, b) (::std::pow(a, b))
+ #endif
+ #else
+ #define __Pyx_c_is_zerof(z) ((z)==0)
+ #define __Pyx_c_conjf(z) (conjf(z))
+ #if 1
+ #define __Pyx_c_absf(z) (cabsf(z))
+ #define __Pyx_c_powf(a, b) (cpowf(a, b))
+ #endif
+ #endif
+#else
+ static CYTHON_INLINE int __Pyx_c_eqf(__pyx_t_float_complex, __pyx_t_float_complex);
+ static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sumf(__pyx_t_float_complex, __pyx_t_float_complex);
+ static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_difff(__pyx_t_float_complex, __pyx_t_float_complex);
+ static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prodf(__pyx_t_float_complex, __pyx_t_float_complex);
+ static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quotf(__pyx_t_float_complex, __pyx_t_float_complex);
+ static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_negf(__pyx_t_float_complex);
+ static CYTHON_INLINE int __Pyx_c_is_zerof(__pyx_t_float_complex);
+ static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conjf(__pyx_t_float_complex);
+ #if 1
+ static CYTHON_INLINE float __Pyx_c_absf(__pyx_t_float_complex);
+ static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_powf(__pyx_t_float_complex, __pyx_t_float_complex);
+ #endif
+#endif
+
+/* None.proto */
+static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double, double);
+
+/* None.proto */
+#if CYTHON_CCOMPLEX
+ #define __Pyx_c_eq(a, b) ((a)==(b))
+ #define __Pyx_c_sum(a, b) ((a)+(b))
+ #define __Pyx_c_diff(a, b) ((a)-(b))
+ #define __Pyx_c_prod(a, b) ((a)*(b))
+ #define __Pyx_c_quot(a, b) ((a)/(b))
+ #define __Pyx_c_neg(a) (-(a))
+ #ifdef __cplusplus
+ #define __Pyx_c_is_zero(z) ((z)==(double)0)
+ #define __Pyx_c_conj(z) (::std::conj(z))
+ #if 1
+ #define __Pyx_c_abs(z) (::std::abs(z))
+ #define __Pyx_c_pow(a, b) (::std::pow(a, b))
+ #endif
+ #else
+ #define __Pyx_c_is_zero(z) ((z)==0)
+ #define __Pyx_c_conj(z) (conj(z))
+ #if 1
+ #define __Pyx_c_abs(z) (cabs(z))
+ #define __Pyx_c_pow(a, b) (cpow(a, b))
+ #endif
+ #endif
+#else
+ static CYTHON_INLINE int __Pyx_c_eq(__pyx_t_double_complex, __pyx_t_double_complex);
+ static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum(__pyx_t_double_complex, __pyx_t_double_complex);
+ static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff(__pyx_t_double_complex, __pyx_t_double_complex);
+ static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod(__pyx_t_double_complex, __pyx_t_double_complex);
+ static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot(__pyx_t_double_complex, __pyx_t_double_complex);
+ static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg(__pyx_t_double_complex);
+ static CYTHON_INLINE int __Pyx_c_is_zero(__pyx_t_double_complex);
+ static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj(__pyx_t_double_complex);
+ #if 1
+ static CYTHON_INLINE double __Pyx_c_abs(__pyx_t_double_complex);
+ static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow(__pyx_t_double_complex, __pyx_t_double_complex);
+ #endif
+#endif
+
+/* CIntToPy.proto */
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value);
+
+/* CIntToPy.proto */
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__NPY_TYPES(enum NPY_TYPES value);
+
+/* CIntFromPy.proto */
+static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *);
+
+/* CIntToPy.proto */
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value);
+
+/* CIntFromPy.proto */
+static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *);
+
+/* CheckBinaryVersion.proto */
+static int __Pyx_check_binary_version(void);
+
+/* PyIdentifierFromString.proto */
+#if !defined(__Pyx_PyIdentifier_FromString)
+#if PY_MAJOR_VERSION < 3
+ #define __Pyx_PyIdentifier_FromString(s) PyString_FromString(s)
+#else
+ #define __Pyx_PyIdentifier_FromString(s) PyUnicode_FromString(s)
+#endif
+#endif
+
+/* ModuleImport.proto */
+static PyObject *__Pyx_ImportModule(const char *name);
+
+/* TypeImport.proto */
+static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, size_t size, int strict);
+
+/* InitStrings.proto */
+static int __Pyx_InitStrings(__Pyx_StringTabEntry *t);
+
+
+/* Module declarations from 'cython' */
+
+/* Module declarations from 'cpython.buffer' */
+
+/* Module declarations from 'libc.string' */
+
+/* Module declarations from 'libc.stdio' */
+
+/* Module declarations from '__builtin__' */
+
+/* Module declarations from 'cpython.type' */
+static PyTypeObject *__pyx_ptype_7cpython_4type_type = 0;
+
+/* Module declarations from 'cpython' */
+
+/* Module declarations from 'cpython.object' */
+
+/* Module declarations from 'cpython.ref' */
+
+/* Module declarations from 'libc.stdlib' */
+
+/* Module declarations from 'numpy' */
+
+/* Module declarations from 'numpy' */
+static PyTypeObject *__pyx_ptype_5numpy_dtype = 0;
+static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0;
+static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0;
+static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0;
+static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0;
+static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *, char *, char *, int *); /*proto*/
+
+/* Module declarations from 'cityscapesscripts.evaluation.addToConfusionMatrix' */
+static PyObject *__pyx_f_17cityscapesscripts_10evaluation_20addToConfusionMatrix_tonumpyarray(unsigned PY_LONG_LONG *, unsigned PY_LONG_LONG); /*proto*/
+static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_uint8_t = { "uint8_t", NULL, sizeof(__pyx_t_5numpy_uint8_t), { 0 }, 0, IS_UNSIGNED(__pyx_t_5numpy_uint8_t) ? 'U' : 'I', IS_UNSIGNED(__pyx_t_5numpy_uint8_t), 0 };
+static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_uint64_t = { "uint64_t", NULL, sizeof(__pyx_t_5numpy_uint64_t), { 0 }, 0, IS_UNSIGNED(__pyx_t_5numpy_uint64_t) ? 'U' : 'I', IS_UNSIGNED(__pyx_t_5numpy_uint64_t), 0 };
+static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_ulonglong_t = { "ulonglong_t", NULL, sizeof(__pyx_t_5numpy_ulonglong_t), { 0 }, 0, IS_UNSIGNED(__pyx_t_5numpy_ulonglong_t) ? 'U' : 'I', IS_UNSIGNED(__pyx_t_5numpy_ulonglong_t), 0 };
+#define __Pyx_MODULE_NAME "cityscapesscripts.evaluation.addToConfusionMatrix"
+int __pyx_module_is_main_cityscapesscripts__evaluation__addToConfusionMatrix = 0;
+
+/* Implementation of 'cityscapesscripts.evaluation.addToConfusionMatrix' */
+static PyObject *__pyx_builtin_ValueError;
+static PyObject *__pyx_builtin_range;
+static PyObject *__pyx_builtin_RuntimeError;
+static const char __pyx_k_np[] = "np";
+static const char __pyx_k_copy[] = "copy";
+static const char __pyx_k_main[] = "__main__";
+static const char __pyx_k_test[] = "__test__";
+static const char __pyx_k_dtype[] = "dtype";
+static const char __pyx_k_numpy[] = "numpy";
+static const char __pyx_k_range[] = "range";
+static const char __pyx_k_uint8[] = "uint8";
+static const char __pyx_k_ctypes[] = "ctypes";
+static const char __pyx_k_import[] = "__import__";
+static const char __pyx_k_width_ui[] = "width_ui";
+static const char __pyx_k_height_ui[] = "height_ui";
+static const char __pyx_k_ulonglong[] = "ulonglong";
+static const char __pyx_k_ValueError[] = "ValueError";
+static const char __pyx_k_confMatrix[] = "confMatrix";
+static const char __pyx_k_evalLabels[] = "evalLabels";
+static const char __pyx_k_RuntimeError[] = "RuntimeError";
+static const char __pyx_k_confMatrix_c[] = "confMatrix_c";
+static const char __pyx_k_cEvaluatePair[] = "cEvaluatePair";
+static const char __pyx_k_confMatDim_ui[] = "confMatDim_ui";
+static const char __pyx_k_predictionArr[] = "predictionArr";
+static const char __pyx_k_groundTruthArr[] = "groundTruthArr";
+static const char __pyx_k_predictionArr_c[] = "predictionArr_c";
+static const char __pyx_k_groundTruthArr_c[] = "groundTruthArr_c";
+static const char __pyx_k_ascontiguousarray[] = "ascontiguousarray";
+static const char __pyx_k_ndarray_is_not_C_contiguous[] = "ndarray is not C contiguous";
+static const char __pyx_k_hd_data_cityscapes_cityscapesSc[] = "/hd-data/cityscapes/cityscapesScripts/cityscapesscripts/evaluation/addToConfusionMatrix.pyx";
+static const char __pyx_k_unknown_dtype_code_in_numpy_pxd[] = "unknown dtype code in numpy.pxd (%d)";
+static const char __pyx_k_Format_string_allocated_too_shor[] = "Format string allocated too short, see comment in numpy.pxd";
+static const char __pyx_k_Non_native_byte_order_not_suppor[] = "Non-native byte order not supported";
+static const char __pyx_k_cityscapesscripts_evaluation_add[] = "cityscapesscripts.evaluation.addToConfusionMatrix";
+static const char __pyx_k_ndarray_is_not_Fortran_contiguou[] = "ndarray is not Fortran contiguous";
+static const char __pyx_k_Format_string_allocated_too_shor_2[] = "Format string allocated too short.";
+static PyObject *__pyx_kp_u_Format_string_allocated_too_shor;
+static PyObject *__pyx_kp_u_Format_string_allocated_too_shor_2;
+static PyObject *__pyx_kp_u_Non_native_byte_order_not_suppor;
+static PyObject *__pyx_n_s_RuntimeError;
+static PyObject *__pyx_n_s_ValueError;
+static PyObject *__pyx_n_s_ascontiguousarray;
+static PyObject *__pyx_n_s_cEvaluatePair;
+static PyObject *__pyx_n_s_cityscapesscripts_evaluation_add;
+static PyObject *__pyx_n_s_confMatDim_ui;
+static PyObject *__pyx_n_s_confMatrix;
+static PyObject *__pyx_n_s_confMatrix_c;
+static PyObject *__pyx_n_s_copy;
+static PyObject *__pyx_n_s_ctypes;
+static PyObject *__pyx_n_s_dtype;
+static PyObject *__pyx_n_s_evalLabels;
+static PyObject *__pyx_n_s_groundTruthArr;
+static PyObject *__pyx_n_s_groundTruthArr_c;
+static PyObject *__pyx_kp_s_hd_data_cityscapes_cityscapesSc;
+static PyObject *__pyx_n_s_height_ui;
+static PyObject *__pyx_n_s_import;
+static PyObject *__pyx_n_s_main;
+static PyObject *__pyx_kp_u_ndarray_is_not_C_contiguous;
+static PyObject *__pyx_kp_u_ndarray_is_not_Fortran_contiguou;
+static PyObject *__pyx_n_s_np;
+static PyObject *__pyx_n_s_numpy;
+static PyObject *__pyx_n_s_predictionArr;
+static PyObject *__pyx_n_s_predictionArr_c;
+static PyObject *__pyx_n_s_range;
+static PyObject *__pyx_n_s_test;
+static PyObject *__pyx_n_s_uint8;
+static PyObject *__pyx_n_s_ulonglong;
+static PyObject *__pyx_kp_u_unknown_dtype_code_in_numpy_pxd;
+static PyObject *__pyx_n_s_width_ui;
+static PyObject *__pyx_pf_17cityscapesscripts_10evaluation_20addToConfusionMatrix_cEvaluatePair(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_predictionArr, PyArrayObject *__pyx_v_groundTruthArr, PyArrayObject *__pyx_v_confMatrix, CYTHON_UNUSED PyObject *__pyx_v_evalLabels); /* proto */
+static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */
+static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info); /* proto */
+static PyObject *__pyx_tuple_;
+static PyObject *__pyx_tuple__2;
+static PyObject *__pyx_tuple__3;
+static PyObject *__pyx_tuple__4;
+static PyObject *__pyx_tuple__5;
+static PyObject *__pyx_tuple__6;
+static PyObject *__pyx_tuple__7;
+static PyObject *__pyx_codeobj__8;
+
+/* "cityscapesscripts/evaluation/addToConfusionMatrix.pyx":19
+ *
+ *
+ * cdef tonumpyarray(unsigned long long* data, unsigned long long size): # <<<<<<<<<<<<<<
+ * if not (data and size >= 0): raise ValueError
+ * return np.PyArray_SimpleNewFromData(2, [size, size], np.NPY_UINT64,