论文:: Consolidation of Unorganized Point Clouds for Surface Reconstruction(WLOP)

主要的核心思想:输入一组点云,然后随机选取最后保留下来的点云,通过加权距离去调整输出点云的位置

更新点云:

#ifndef DDX_WLOP_HEADER
#define DDX_WLOP_HEADER
#pragma once #include <vector>
#include <memory>
#include <Eigen/Dense>
#include "KDTreeFlann.h"
#include "KDTreeSearchParam.h"
#include <random>
#include <omp.h>
#include <iostream>
#include <fstream>namespace DDX {class WLOP
{
public:EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
private:double mRadius;double mMu;int mSelect_percentage;bool require_uniform_sampling;std::vector<Eigen::Vector3d>& original_point;std::vector<Eigen::Vector3d> sample_points ;public:WLOP(std::vector<Eigen::Vector3d>& point , double radius ,int percentage  ,double mu = 0.45 ,bool density = false):original_point(point),mRadius (radius) ,mMu(mu) ,mSelect_percentage(percentage) ,require_uniform_sampling (density){};void Run (int iter_number) {size_t number_of_original = original_point.size() ;size_t number_of_sample = static_cast<size_t> (float(number_of_original) * (mSelect_percentage / float(100.0))) ;std::vector<Eigen::Vector3d> update_sample_points(number_of_sample);// 1 按照百分比生成下采样的点sample_points.reserve (number_of_sample);generate_sample_points(number_of_original ,number_of_sample);std::cout << "number_of_sample " << number_of_sample << std::endl;std::cout << "sample_points size " << sample_points.size() << std::endl;// 2 初始化一个原始的kd tree const auto original_kd_tree = create_Kdtree (original_point);std::vector<double> original_density (number_of_original);std::vector<double> samples_density (number_of_sample);if (require_uniform_sampling) {for (int i = 0 ; i < (int)original_point.size() ;++i){original_density[i] = compute_density_weight_for_original_point (original_kd_tree ,original_point[i] ,mRadius);}}// 3 迭代更新for (int iter_n = 0; iter_n < iter_number; ++iter_n) {std::cout << "iter " << iter_n << std::endl;// 创建采样点的kd tree const auto sample_kd_tree = create_Kdtree (sample_points);for (int i = 0 ; i < (int)sample_points.size() ; ++i){samples_density[i] = compute_density_weight_for_sample_point (sample_kd_tree ,sample_points[i] ,mRadius);}for (int i = 0 ; i < (int)sample_points.size() ; ++i) {update_sample_points[i] = compute_update_sample_point (i ,original_kd_tree ,sample_kd_tree ,original_density ,samples_density ,mRadius);}for (int i = 0 ; i < (int)update_sample_points.size() ; ++i) {sample_points[i] = update_sample_points[i];}}} ;void write_obj (const std::string& path) {std::ofstream delaunay3d (path.c_str());for (int i = 0 ; i < sample_points.size() ; ++i) {delaunay3d << "v " << sample_points[i][0] << " "<< sample_points[i][1] << " "<< sample_points[i][2] << std::endl ;}delaunay3d.close ();}
private:    std::unique_ptr<KDTreeFlann> create_Kdtree (std::vector<Eigen::Vector3d>& point) {Eigen::MatrixXd dataset0 = Eigen::Map<Eigen::MatrixXd>(reinterpret_cast<double*>(point.data()),3,point.size());return std::make_unique<KDTreeFlann> (dataset0) ;};void generate_sample_points (size_t number_of_original, size_t number_of_sample ) {size_t diff_number = number_of_original - number_of_sample;std::random_device rd ; std::mt19937 gen(rd()) ; constexpr int int_max = std::numeric_limits<int>::max () ;std::uniform_int_distribution<int> dis(int(0),int_max) ;std::vector<int> vist (number_of_original ,-1);int count_indx = 0;while (count_indx < diff_number ){int randint = dis (gen) ;const auto i13x = randint % (int)number_of_original ;if (vist[i13x] < 0) {vist[i13x] = 1;count_indx++;}}for (size_t i = 0 ; i < number_of_original ; ++i) {if (vist[i] < 0)sample_points.push_back (original_point[i]);}}double compute_density_weight_for_original_point (const std::unique_ptr<KDTreeFlann>& original_kd_tree ,Eigen::Vector3d const&p ,double radius ){double radius2 = radius * radius;double density_weight = (double)1.0;double iradius16 = -(double)4.0 / radius2;std::vector<int> index ;std::vector<double> distance ;const auto k = original_kd_tree->SearchRadius (p ,radius ,index ,distance) ;for (int i = 0 ; i < k ; ++i) {if (distance[i] < 1e-8) continue;density_weight += std::exp(distance[i] * iradius16);}return double(1.0) / density_weight;};double compute_density_weight_for_sample_point (const std::unique_ptr<KDTreeFlann>& sample_kd_tree  ,Eigen::Vector3d const&p ,double radius){//Compute density weightdouble radius2 = radius * radius;double density_weight = (double)1.0;double iradius16 = -(double)4.0 / radius2;std::vector<int> index ;std::vector<double> distance ;const auto k = sample_kd_tree->SearchRadius (p ,radius ,index ,distance) ;for (int i = 0 ; i < k ; ++i) {density_weight += std::exp(distance[i] * iradius16);}return density_weight;};Eigen::Vector3d compute_update_sample_point (int indx ,const std::unique_ptr<KDTreeFlann>& original_kd_tree,const std::unique_ptr<KDTreeFlann>& sample_kd_tree ,const std::vector<double>& sample_densities ,const std::vector<double> original_densities ,double radius) {bool is_original_densities_empty = original_densities.empty();bool is_sample_densities_empty = sample_densities.empty();double radius2 = radius * radius;double iradius16 = -(double)4.0 / radius2;// Compute Average TermEigen::Vector3d average (0 , 0 ,0);if (true) {    double average_weight_sum = (double)0.0;std::vector<int> index ;std::vector<double> distance ; const auto k = original_kd_tree->SearchRadius (sample_points[indx] , radius ,index ,distance);for (int j = 0 ; j < k ; j++){double dist2 = distance[j];if (dist2 < 1e-10) continue;double weight = (double)0.0;weight = std::exp(dist2 * iradius16);if (!is_original_densities_empty){weight *= original_densities[index[j]];}average_weight_sum += weight;average += original_point[index[j]] * weight;}if (k == 0 || average_weight_sum < 1e-20){average = sample_points[indx] ;}else{average = average / average_weight_sum;}}//Compute repulsion termEigen::Vector3d repulsion (0.0 , 0.0 ,0.0);if (true) {double weight = (double)1.0;double repulsion_weight_sum = (double)0.0;std::vector<int> index ;std::vector<double> distance ; const auto k = sample_kd_tree->SearchRadius (sample_points[indx] , radius ,index ,distance);for (int j = 0 ; j < k ; j++){double dist2 = distance[j];if (dist2 < 1e-10) continue;double dist = std::sqrt(dist2);weight = std::exp(dist2 * iradius16) * std::pow(double(1.0) / dist ,2); // L1if (!is_sample_densities_empty){weight *= sample_densities[index[j]];}Eigen::Vector3d diff = sample_points[indx] - sample_points[index[j]];repulsion_weight_sum += weight;repulsion = repulsion + diff * weight;}if (k < 3 || repulsion_weight_sum < double(1e-20)) {repulsion = Eigen::Vector3d(0.0 ,0.0 ,0.0);}else {repulsion = repulsion / repulsion_weight_sum;}}return average + mMu * repulsion ;  };};}#endif /* DDX_WLOP_HEADER */

githut: GitHub - xiandenis/WLOP: Consolidation of Unorganized Point Clouds for Surface Reconstruction

Consolidation of Unorganized Point Clouds for Surface Reconstruction(WLOP)的代码相关推荐

  1. Learning Occupancy Function from Point Clouds for Surface Reconstruction论文笔记

    Motivation&Contribution recent implicit function-based shape-learning methods focus only more on ...

  2. 泊松重建(Poisson Surface Reconstruction)

    简介 泊松重建是Michael Kazhdan等在2006年提出的网格重建方法,其文章题目为"Poisson Surface Reconstruction". Poisson-Re ...

  3. Screened Poisson Surface Reconstruction (Version 8.0)

    转自:https://www.cs.jhu.edu/~misha/Code/PoissonRecon/Version8.0/ linksexecutablesusagechanges LINKS Pa ...

  4. [CVPR2021 Oral] PREDATOR: Registration of 3D Point Clouds with Low Overlap 损失函数含代码理解

    PREDATOR: Registration of 3D Point Clouds with Low Overlap 损失函数含代码理解 Overlap loss,Matchability loss ...

  5. Surface reconstruction from unorganized points

    一. 原论文链接 本文描述了一种算法,输入未知实体M上或者附近的无序的数据点集合{x1,x2,-,xn},建立一个隐式函数代表点到实体M的符号距离,最后提取函数的零等值面,得到实体M的近似曲面. 1. ...

  6. Poisson Surface Reconstruction

    http://vr.tu-freiberg.de/scivi/?page_id=365 转载于:https://www.cnblogs.com/guochen/p/6567453.html

  7. Screened Poisson Surface Reconstruction

    http://www.cs.jhu.edu/~misha/Code/PoissonRecon/Version9.01/ 转载于:https://www.cnblogs.com/guochen/p/65 ...

  8. 图形学必备!斯坦福图形学几何处理算法课程1——Surface Reconstruction

    表面重建,通过扫描设备扫描获得点云,之后重建 下面就是具体的扫描系统,问题是要在两个图片上匹配特征 激光脉冲,适用于远距离大物体, 依赖于测量时间的准确性 目标是从扫描集重建物体 方法一是以一个扫描覆 ...

  9. 经典点云去噪算法总结

    以下列出方法均有运行成功的代码,所有工程文件我都会放在如下链接: https://github.com/gx-sun/classic-point-cloud-denoising-methods 欢迎s ...

  10. 图形处理(九)点云重建(下)法矢求取、有向距离场等值面提取

    一.相关理论 在点云重建算法中,点云法矢的求取是非常重要的一步.之前导师让我做点云尖锐特征边重建时,发了一堆异向法矢求取的英文paper,当时我很迷糊,就问了老师,让我做点云重建,为什么发的文献资料都 ...

最新文章

  1. 从源码分析DEARGUI之让怪物随机动起来
  2. Linux如何实现断点续传文件功能?
  3. hdu 4568 Hunter bfs建图+TSP状压DP
  4. mysql为什么要转es_MySQL用得好好的,为什么要转ES?
  5. 操作系统实验报告9:进程间通信—管道和 socket 通信
  6. python与数据库连接的代码_python连接数据库的案例及源代码
  7. 升级xcode5.1 iOS 6.0后以前的横屏项目 变为了竖屏
  8. creo动画如何拖动主体_Animate如何制作动态遮罩文字动画
  9. DB2 错误代码 命令大全
  10. HTTP 04 web 服务器
  11. 信用指數旁的星星表示什麼?
  12. c#使用 Newtonsoft.Json 将entity转json时,忽略为null的属性
  13. vs---编写第一个JavaScript程序
  14. eclipse html插件的下载和安装
  15. python连接cx_oracle时报错DatabaseError: DPI-1047: 64-bit Oracle Client library cannot be loaded:
  16. 将文件中的单词及翻译导入数据库
  17. linux新硬盘装系统,目前是windows,要全新硬盘安装linux,该怎么操作?
  18. sap--TCODE 之 SE93 将事务代码分配给程序(转)
  19. Java List转Map时发生Duplicate key
  20. bigDecimal学习笔记_隋小白

热门文章

  1. 给十二星座的12封信,句句说中你们的心理要害!
  2. 【嵌入式系统】STM32时钟系统+时钟配置函数解析
  3. 充电识别过程及QC2.0
  4. LeetCode 263 Ugly Number(丑数)
  5. 2021年全球与中国数字射线照相设备行业市场规模及发展前景分析
  6. ?迅捷PDF转换成word转换器在线使用方法
  7. 用流量扫码总显示无法连接服务器,手机有流量但无法连接网络?手机数据网络不能访问互联网...
  8. Local time zone must be set-see zic manual page
  9. Gos —— 开启中断与中断机制详解
  10. uni-app 使用外部.js文件定义全局变量和全局方法