Пример #1
0
/**
 * @brief   Main entry point for the LSSR surface executable
 */
int main(int argc, char** argv)
{
	try
	{
		// Parse command line arguments
		reconstruct::Options options(argc, argv);

		// Exit if options had to generate a usage message
		// (this means required parameters are missing)
		if ( options.printUsage() )
		{
			return 0;
		}

		omp_set_num_threads(options.getNumThreads());

		::std::cout << options << ::std::endl;

		// Create a point loader object
		ModelFactory io_factory;
		ModelPtr model = io_factory.readModel( options.getInputFileName() );
		PointBufferPtr p_loader;

		// Parse loaded data
		if ( !model )
		{
			cout << timestamp << "IO Error: Unable to parse " << options.getInputFileName() << endl;
			exit(-1);
		}
		p_loader = model->m_pointCloud;

		// Create a point cloud manager
		string pcm_name = options.getPCM();
		psSurface::Ptr surface;

		// Create point set surface object
		if(pcm_name == "PCL")
		{
#ifdef _USE_PCL_
			surface = psSurface::Ptr( new pclSurface(p_loader));
#else 
			cout << timestamp << "Can't create a PCL point set surface without PCL installed." << endl;
			exit(-1);
#endif
		}
		else if(pcm_name == "STANN" || pcm_name == "FLANN" || pcm_name == "NABO" || pcm_name == "NANOFLANN")
		{
			akSurface* aks = new akSurface(
					p_loader, pcm_name,
					options.getKn(),
					options.getKi(),
					options.getKd()
			);

			surface = psSurface::Ptr(aks);
			// Set RANSAC flag
			if(options.useRansac())
			{
				aks->useRansac(true);
			}
		}
		else
		{
			cout << timestamp << "Unable to create PointCloudManager." << endl;
			cout << timestamp << "Unknown option '" << pcm_name << "'." << endl;
			cout << timestamp << "Available PCMs are: " << endl;
			cout << timestamp << "STANN, STANN_RANSAC";
#ifdef _USE_PCL_
			cout << ", PCL";
#endif
#ifdef _USE_NABO
			cout << ", Nabo";
#endif
			cout << endl;
			return 0;
		}

		// Set search options for normal estimation and distance evaluation
		surface->setKd(options.getKd());
		surface->setKi(options.getKi());
		surface->setKn(options.getKn());

		// Calculate normals if necessary
		if(!surface->pointBuffer()->hasPointNormals()
				|| (surface->pointBuffer()->hasPointNormals() && options.recalcNormals()))
		{
		    Timestamp ts;
			surface->calculateSurfaceNormals();
			cerr << ts.getElapsedTimeInMs() << endl;
		}
		else
		{
			cout << timestamp << "Using given normals." << endl;
		}

		// Save points and normals only
		if(options.savePointNormals())
		{
			ModelPtr pn( new Model);
			pn->m_pointCloud = surface->pointBuffer();
			ModelFactory::saveModel(pn, "pointnormals.ply");
		}

		// Create an empty mesh
		HalfEdgeMesh<cVertex, cNormal> mesh( surface );

		// Set recursion depth for region growing
		if(options.getDepth())
		{
			mesh.setDepth(options.getDepth());
		}

		if(options.getTexelSize())
		{
			Texture::m_texelSize = options.getTexelSize();
		}
		
		if(options.getTexturePack() != "")
		{
			Texturizer<cVertex, cNormal>::m_filename = options.getTexturePack();
			if(options.getStatsCoeffs())
			{	
				float* sc = options.getStatsCoeffs();
				for (int i = 0; i < 14; i++)
				{
					Statistics::m_coeffs[i] = sc[i];
				}
				delete sc;
			}
			if(options.getNumStatsColors())
			{
				Texturizer<cVertex, cNormal>::m_numStatsColors = options.getNumStatsColors();
			}
			if(options.getNumCCVColors())
			{
				Texturizer<cVertex, cNormal>::m_numCCVColors = options.getNumCCVColors();
			}
			if(options.getCoherenceThreshold())
			{
				Texturizer<cVertex, cNormal>::m_coherenceThreshold = options.getCoherenceThreshold();
			}

			if(options.getColorThreshold())
			{
				Texturizer<cVertex, cNormal>::m_colorThreshold = options.getColorThreshold();
			}
			if(options.getStatsThreshold())
			{
				Texturizer<cVertex, cNormal>::m_statsThreshold = options.getStatsThreshold();
			}
			if(options.getUseCrossCorr())
			{
				Texturizer<cVertex, cNormal>::m_useCrossCorr = options.getUseCrossCorr();
			}
			if(options.getFeatureThreshold())
			{
				Texturizer<cVertex, cNormal>::m_featureThreshold = options.getFeatureThreshold();
			}
			if(options.getPatternThreshold())
			{
				Texturizer<cVertex, cNormal>::m_patternThreshold = options.getPatternThreshold();
			}
			if(options.doTextureAnalysis())
			{
			    Texturizer<cVertex, cNormal>::m_doAnalysis = true;
			}
			if(options.getMinimumTransformationVotes())
			{
				Transform::m_minimumVotes = options.getMinimumTransformationVotes();
			}
		}

		if(options.getSharpFeatureThreshold())
		{
			SharpBox<cVertex, cNormal>::m_theta_sharp = options.getSharpFeatureThreshold();
		}
		if(options.getSharpCornerThreshold())
		{
			SharpBox<cVertex, cNormal>::m_phi_corner = options.getSharpCornerThreshold();
		}

		// Determine whether to use intersections or voxelsize
		float resolution;
		bool useVoxelsize;
		if(options.getIntersections() > 0)
		{
			resolution = options.getIntersections();
			useVoxelsize = false;
		}
		else
		{
			resolution = options.getVoxelsize();
			useVoxelsize = true;
		}

		// Create a new reconstruction object

		FastReconstruction<cVertex, cNormal > reconstruction(
				surface,
				resolution,
				useVoxelsize,
				options.getDecomposition(),
				options.extrude());
		
		
		// Create mesh
		 reconstruction.getMesh(mesh); // kleines Speicherleck noch vorhanden
		
		// Save grid to file
		if(options.saveGrid())
		{
			reconstruction.saveGrid("fastgrid.grid");
		}

		if(options.getDanglingArtifacts())
		{
			mesh.removeDanglingArtifacts(options.getDanglingArtifacts());
		}

		// Optimize mesh
		mesh.cleanContours(options.getCleanContourIterations());
		mesh.setClassifier(options.getClassifier());

		if(options.optimizePlanes())
		{
			mesh.optimizePlanes(options.getPlaneIterations(),
					options.getNormalThreshold(),
					options.getMinPlaneSize(),
					options.getSmallRegionThreshold(),
					true);

			mesh.fillHoles(options.getFillHoles());

			mesh.optimizePlaneIntersections();

			mesh.restorePlanes(options.getMinPlaneSize());

			if(options.getNumEdgeCollapses())
			{
				QuadricVertexCosts<cVertex, cNormal> c = QuadricVertexCosts<cVertex, cNormal>(true);
				mesh.reduceMeshByCollapse(options.getNumEdgeCollapses(), c);
			}
		}
		else if(options.clusterPlanes())
		{
			mesh.clusterRegions(options.getNormalThreshold(), options.getMinPlaneSize());
			mesh.fillHoles(options.getFillHoles());
		}

		// Save triangle mesh
		if ( options.retesselate() )
		{
			mesh.finalizeAndRetesselate(options.generateTextures(),
					options.getLineFusionThreshold());
		}
		else
		{
			mesh.finalize();
		}

		// Create output model and save to file
		ModelPtr m( new Model( mesh.meshBuffer() ) );
		
		if(options.saveOriginalData())
		{
			m->m_pointCloud = model->m_pointCloud;
		}
		cout << timestamp << "Saving mesh." << endl;
		ModelFactory::saveModel( m, "triangle_mesh.ply");

		// Save obj model if textures were generated
		if(options.generateTextures())
		{
			ModelFactory::saveModel( m, "triangle_mesh.obj");
		}		
		cout << timestamp << "Program end." << endl;

	}
	catch(...)
	{
		std::cout << "Unable to parse options. Call 'reconstruct --help' for more information." << std::endl;
	}
	return 0;
}