main.cpp 5.45 KB
#include <stdlib.h>
#include <string>
#include <fstream>
#include <algorithm>

//OpenGL includes
#include <GL/glut.h>

//STIM includes
#include <stim/visualization/gl_network.h>
#include <stim/visualization/gl_aabb.h>
#include <stim/parser/arguments.h>
#include <stim/visualization/camera.h>

//ANN includes
#include <ANN/ANN.h>

//BOOST includes
#include <boost/tuple/tuple.hpp>

stim::gl_aabb<float> bb;
stim::camera cam;

stim::gl_network<float> GT;
stim::gl_network<float> T;

//hard-coded parameters
float resample_rate = 0.5;

//mouse position tracking
int mouse_x;
int mouse_y;

void glut_render(void) {

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	stim::vec<float> eye = cam.getPosition();
	stim::vec<float> focus = cam.getLookAt();
	stim::vec<float> up = cam.getUp();

	gluLookAt(eye[0], eye[1], eye[2], focus[0], focus[1], focus[2], up[0], up[1], up[2]);

	

	// render the bounding box
	glColor3f(0.0, 0.0, 1.0);
	glBegin(GL_LINE_LOOP);
		bb.glPointsCW();
	glEnd();

	//render the GT network (red)
	glColor3f(1.0, 0.0, 0.0);
	GT.glCenterline();

	//render the T network (green)
	glColor3f(0.0, 1.0, 0.0);
	T.glCenterline();

	glutSwapBuffers();
}

// defines camera motion based on mouse dragging
void glut_motion(int x, int y){
	float factor = 0.01;

	float theta = factor * (mouse_x - x);
	float phi = factor * (y - mouse_y);

	cam.OrbitFocus(theta, phi);

	mouse_x = x;
	mouse_y = y;

	glutPostRedisplay();
}

// sets the mouse position when clicked
void glut_mouse(int button, int state, int x, int y){
	mouse_x = x;
	mouse_y = y;
}

// re-calculates the projection matrix if the window is reshaped
void glut_reshape(int x, int y){

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glViewport(0, 0, x, y);
	float aspect = (float)x / (float)y;
	gluPerspective(60, aspect, 0.1, 1000000);

}

void advertise(){
	//output advertisement
	std::cout<<std::endl<<std::endl;
	std::cout<<"========================================================================="<<std::endl;
	std::cout<<"Thank you for using the NetMets network comparison tool!"<<std::endl;
	std::cout<<"Scalable Tissue Imaging and Modeling (STIM) Lab, University of Houston"<<std::endl;
	std::cout<<"Developers: Pranathi Vemuri, David Mayerich"<<std::endl;
	std::cout<<"Source: https://git.stim.ee.uh.edu/segmentation/netmets"<<std::endl;
	std::cout<<"========================================================================="<<std::endl<<std::endl;

	std::cout<<"usage: netmets file1 file2 --sigma 10"<<std::endl;
	std::cout<<"            compare two files with a tolerance of 10 (units defined by the network)"<<std::endl;
	std::cout<<"       netmets file1 --gui"<<std::endl<<std::endl;
	std::cout<<"            load a file and display it using OpenGL"<<std::endl;

}

void compare(float sigma){

	// compare ground truth with truth and viceversa
	stim::network<float> cGT = GT.compare(T, sigma);
    stim::network<float> cT = T.compare(GT, sigma);

	//calculate the metrics
	float FPR = cGT.average(1);
	float FNR = cT.average(1);
	// print false alarms and misses
	std::cout << "FNR: " << FPR << std::endl;
	std::cout << "FPR: " << FNR << std::endl;
}

void glut_initialize(){
	float factor = 1.2;

	// init GLUT and create Window
	int myargc = 1;
	char* myargv[1];
	myargv [0]=strdup ("netmets");

	glutInit(&myargc, myargv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(100,100);
	glutInitWindowSize(320,320);
	glutCreateWindow("Lighthouse3D- GLUT Tutorial");

	
	// register callbacks
	glutDisplayFunc(glut_render);
	glutMouseFunc(glut_mouse);
	glutMotionFunc(glut_motion);
	glutReshapeFunc(glut_reshape);

	//set up the camera
	stim::vec<float> c = bb.center();
	//place the camera along the z-axis at a distance determined by the network size along x and y
	cam.setPosition(c + stim::vec<float>(0, 0, factor * std::max(bb.size()[0], bb.size()[1])));
	cam.LookAt(c[0], c[1], c[2]);						//look at the center

}

void display(){


	//generate a bounding volume
	bb = GT.boundingbox();

	std::cout<<bb.str()<<std::endl;

	std::cout<<"center: "<<bb.center().str()<<std::endl;
	std::cout<<"size:   "<<bb.size().str()<<std::endl;

	//create the GLUT window and set callback functions
	glut_initialize();

	glut_reshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));

	std::cout<<cam.str()<<std::endl;

	// enter GLUT event processing cycle
	glutMainLoop();
}

int main(int argc, char* argv[])
{
	//create an instance of arglist
	stim::arglist args;

	//add arguments
	args.add("help", "prints this help");
	args.add("sigma", "force a sigma value to specify the tolerance of the network comparison", "10");
	args.add("gui", "display the network or network comparison using OpenGL");

	//parse the user arguments
	args.parse(argc, argv);

	//test for help
	if(args["help"].is_set() || args.nargs() == 0){
		advertise();
		std::cout<<args.str();
		exit(1);
	}

	//if one file is specified, load it as the ground truth
	if(args.nargs() >= 1){
		GT.load_obj(args.arg(0));
	}

	//if two files are provided, compare them
	if(args.nargs() == 2){
		float sigma = args["sigma"].as_float();				//get the sigma value from the user
		T.load_obj(args.arg(1));							//load the second (test) network

		GT = GT.resample(resample_rate * sigma);			//resample both networks based on the sigma value
		T = T.resample(resample_rate * sigma);

		compare(sigma);										//run the comparison algorithm
	}

	//if a GUI is requested, display the network using OpenGL
	if(args["gui"].is_set())
		display();
	

	
}