Grid upsampling, much faster processing

Former-commit-id: e066e9ba2d
pull/1161/head
Piero Toffanin 2017-04-18 10:48:17 -04:00
rodzic 38cf16f6c9
commit cfc8b01ee0
5 zmienionych plików z 95 dodań i 94 usunięć

Wyświetl plik

@ -7,8 +7,8 @@ typedef CGAL::Delaunay_triangulation_2<Kernel, Tds> DT;
typedef DT::Point cgalPoint;
typedef DT::Vertex_circulator Vertex_circulator;
typedef CGAL::First_of_pair_property_map<Pwn> Point_map;
typedef CGAL::Second_of_pair_property_map<Pwn> Normal_map;
//typedef CGAL::First_of_pair_property_map<Pwn> Point_map;
//typedef CGAL::Second_of_pair_property_map<Pwn> Normal_map;
// Concurrency
#ifdef CGAL_LINKED_WITH_TBB
@ -147,48 +147,101 @@ void Odm25dMeshing::loadPointCloud(){
}
void Odm25dMeshing::buildMesh(){
const unsigned int NEIGHBORS = 16;
const unsigned int NEIGHBORS = 24;
size_t pointCount = points.size();
log << "Performing bilateral smoothing... ";
for (int i = 0; i < 3; i++){
double err = CGAL::bilateral_smooth_point_set<Concurrency_tag>(
points.begin(),
points.end(),
Point_map(),
Normal_map(),
NEIGHBORS,
45.0,
Kernel());
log << err << " ";
if (err < 0.001){
log << "stopping early\n";
}else if (i >= 2){
log << "iteration limit reached\n";
}
}
const double RETAIN_PERCENTAGE = std::min<double>(((100. * (double)maxVertexCount) / (double)pointCount), 80.); // percentage of points to retain.
std::vector<Point3> simplifiedPoints;
log << "Computing average spacing... ";
FT avgSpacing = CGAL::compute_average_spacing<Concurrency_tag>(
points.begin(),
points.end(),
Point_map(),
NEIGHBORS);
log << avgSpacing << "\n";
log << "Grid Z sampling\n";
size_t pointCountBeforeGridSampling = pointCount;
double gridStep = avgSpacing;
Kernel::Iso_cuboid_3 bbox = CGAL::bounding_box(points.begin(), points.end());
Vector3 boxDiag = bbox.max() - bbox.min();
int gridWidth = 1 + static_cast<unsigned>(boxDiag.x() / gridStep + 0.5);
int gridHeight = 1 + static_cast<unsigned>(boxDiag.y() / gridStep + 0.5);
#define KEY(i, j) (i * gridWidth + j)
std::unordered_map<int, Point3> grid;
for (size_t c = 0; c < pointCount; c++){
const Point3 &p = points[c];
Vector3 relativePos = p - bbox.min();
int i = static_cast<int>((relativePos.x() / gridStep + 0.5));
int j = static_cast<int>((relativePos.y() / gridStep + 0.5));
if ((i >= 0 && i < gridWidth) && (j >= 0 && j < gridHeight)){
int key = KEY(i, j);
if (grid.find(key) == grid.end()){
grid[key] = p;
}else if ((!flipFaces && p.z() > grid[key].z()) || (flipFaces && p.z() < grid[key].z())){
grid[key] = p;
}
}
}
std::vector<Point3> gridPoints;
for ( auto it = grid.begin(); it != grid.end(); ++it ){
gridPoints.push_back(it->second);
}
pointCount = gridPoints.size();
log << "Sampled " << (pointCountBeforeGridSampling - pointCount) << " points\n";
log << "Hole filling\n";
std::unordered_map<int, Point3>::iterator it;
for (int i = 1; i < gridWidth - 1; i++){
for (int j = 1; j < gridHeight - 1; j++){
if (grid.find(KEY(i, j)) == grid.end()){
int neighbors = 0;
FT avgZ = 0;
for (int k = i - 1; k < i + 1; k++){
for (int l = j - 1; l < j + 1; l++){
// Search for immediate neighbors
if ((it = grid.find(KEY(k, l))) != grid.end()){
avgZ += it->second.z();
neighbors++;
}
}
}
// Found?
if (neighbors > 0){
gridPoints.push_back(Point3(
(i - 0.5) * gridStep + bbox.min().x(),
(j - 0.5) * gridStep + bbox.min().y(),
avgZ / static_cast<FT>(neighbors)));
}
}
}
}
log << "Filled grid with " << (gridPoints.size() - pointCount) << " points\n";
pointCount = gridPoints.size();
const double RETAIN_PERCENTAGE = std::min<double>(100., 100. * static_cast<double>(maxVertexCount) / static_cast<double>(pointCount)); // percentage of points to retain.
std::vector<Point3> simplifiedPoints;
log << "Performing weighted locally optimal projection simplification and regularization (retain: " << RETAIN_PERCENTAGE << "%, iterate: " << wlopIterations << ")" << "\n";
CGAL::wlop_simplify_and_regularize_point_set<Concurrency_tag>(
points.begin(),
points.end(),
gridPoints.begin(),
gridPoints.end(),
std::back_inserter(simplifiedPoints),
Point_map(),
RETAIN_PERCENTAGE,
8 * avgSpacing,
wlopIterations,
@ -202,59 +255,6 @@ void Odm25dMeshing::buildMesh(){
log << "Vertex count is " << pointCount << "\n";
log << "Z-occlusion filtering\n";
size_t pointCountBeforeOcclusionFiltering = pointCount;
const double gridStep = 0.05;
Kernel::Iso_cuboid_3 bbox = CGAL::bounding_box(simplifiedPoints.begin(), simplifiedPoints.end());
Vector3 boxDiag = bbox.max() - bbox.min();
int gridWidth = 1 + static_cast<unsigned>(boxDiag.x() / gridStep + 0.5);
int gridHeight = 1 + static_cast<unsigned>(boxDiag.y() / gridStep + 0.5);
std::unordered_map<int, Point3> grid;
for (size_t c = 0; c < pointCount; c++){
const Point3 &p = simplifiedPoints[c];
Vector3 relativePos = p - bbox.min();
int i = static_cast<int>((relativePos.x() / gridStep + 0.5));
int j = static_cast<int>((relativePos.y() / gridStep + 0.5));
if ((i >= 0 && i < gridWidth) && (j >= 0 && j < gridHeight)){
int key = i * gridWidth + j;
if (grid.find(key) == grid.end()){
grid[key] = p;
}else if (p.z() > grid[key].z()){
grid[key] = p;
}
//
// if (grid[i][j] == NULL){
// grid[i][j] = static_cast<Point3*>(&p);
// }else if (p.z() > grid[i][j]->z()){
// grid[i][j] = static_cast<Point3*>(&p);
// }
}
}
std::vector<Point3> gridPoints;
for ( auto it = grid.begin(); it != grid.end(); ++it ){
gridPoints.push_back(it->second);
}
// for (int i = 0; i < gridWidth; i++){
// for (int j = 0; j < gridHeight; j++){
// if (grid[i][j] != NULL){
// gridPoints.push_back(*grid[i][j]);
// }
// }
// }
pointCount = gridPoints.size();
log << "Removed " << (pointCountBeforeOcclusionFiltering - pointCount) << " points\n";
std::vector< std::pair<cgalPoint, size_t > > pts;
try{
pts.reserve(pointCount);
@ -263,7 +263,7 @@ void Odm25dMeshing::buildMesh(){
}
for (size_t i = 0; i < pointCount; ++i){
pts.push_back(std::make_pair(cgalPoint(gridPoints[i].x(), gridPoints[i].y()), i));
pts.push_back(std::make_pair(cgalPoint(simplifiedPoints[i].x(), simplifiedPoints[i].y()), i));
}
log << "Computing delaunay triangulation\n";
@ -291,9 +291,9 @@ void Odm25dMeshing::buildMesh(){
for (size_t i = 0; i < pointCount; ++i){
vertices.push_back(gridPoints[i].x());
vertices.push_back(gridPoints[i].y());
vertices.push_back(gridPoints[i].z());
vertices.push_back(simplifiedPoints[i].x());
vertices.push_back(simplifiedPoints[i].y());
vertices.push_back(simplifiedPoints[i].z());
}
for (DT::Face_iterator face = dt.faces_begin(); face != dt.faces_end(); ++face) {

Wyświetl plik

@ -65,7 +65,7 @@ private:
std::string logFilePath = "odm_25dmeshing_log.txt";
unsigned int maxVertexCount = 100000;
unsigned int wlopIterations = 35;
std::vector<Pwn> points;
std::vector<Point3> points;
bool flipFaces = false;
};

Wyświetl plik

@ -19,11 +19,11 @@ void PlyInterpreter::process_line(CGAL::Ply_reader& reader) {
reader.assign (y, "y");
reader.assign (z, "z");
reader.assign (nx, "nx");
reader.assign (ny, "ny");
reader.assign (nz, "nz");
reader.assign (ny, "ny");
reader.assign (nz, "nz");
Point3 p(x, y, z);
Vector3 n(nx, ny, nz);
// Vector3 n(nx, ny, nz);
if (nz >= 0 && zNormalsDirectionCount < std::numeric_limits<long>::max()){
zNormalsDirectionCount++;
@ -31,7 +31,8 @@ void PlyInterpreter::process_line(CGAL::Ply_reader& reader) {
zNormalsDirectionCount--;
}
points.push_back(std::make_pair(p, n));
// points.push_back(std::make_pair(p, n));
points.push_back(p);
}
bool PlyInterpreter::flip_faces(){

Wyświetl plik

@ -16,14 +16,14 @@ typedef Kernel::Point_3 Point3;
typedef Kernel::Vector_3 Vector3;
// points, normals
typedef std::pair<Point3, Vector3> Pwn;
//typedef std::pair<Point3, Vector3> Pwn;
class PlyInterpreter {
std::vector<Pwn>& points;
std::vector<Point3>& points;
long zNormalsDirectionCount;
public:
PlyInterpreter (std::vector<Pwn>& points)
PlyInterpreter (std::vector<Point3>& points)
: points (points), zNormalsDirectionCount(0)
{ }
bool is_applicable (CGAL::Ply_reader& reader);

Wyświetl plik

@ -254,7 +254,7 @@ def config():
parser.add_argument('--mesh-wlop-iterations',
metavar='<positive integer>',
default=70,
default=35,
type=int,
help=('Iterations of the Weighted Locally Optimal Projection (WLOP) simplification algorithm. '
'Higher values take longer but produce a smoother mesh. '