论文:: 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. 法猿生存计划--左边的管理,技术正确
  2. 利用zabbix-java-gateway监控jvm
  3. 一个小网管的淘金梦----深圳往事(4)
  4. 【杂谈】购言有三签名纪念版书籍,送1~3副有三AI学习扑克牌
  5. 初学者python笔记(内置函数_2)
  6. 力扣打家劫舍系列总结
  7. DRUID连接池的使用
  8. Python入门--闭包,工程函数
  9. 抖音直播违规行为与敏感词处罚,直播必备干货大全丨国仁网络
  10. Anaconda快速安装pytorch几分钟离线快速安装一定可行 下载缓慢conda install offline pytorch cudatoolkit slowly
  11. 自动升级WordPress失败解决方法
  12. Python的Scipy库解微分方程
  13. 跟踪fork: Resource temporarily unavailable的原因
  14. JavaScript 实现抢购倒计时,记录恋爱1314纪念日倒计时,输出对应的天数小时分钟秒数
  15. 2019CCPC江苏南京女生赛 | 总结
  16. dw2019连接mysql数据库_VS 2019 连接MySQL数据库配置记录
  17. PTA_Pra 1012 数字分类 (20分)
  18. vue通用后台管理(登录页面)
  19. 浅谈资金发展投资行业的发展路径
  20. 小白终是踏上了这条不归路----小文的mysql学习笔记目录

热门文章

  1. Java 第三阶段增强分析需求,代码实现能力【满汉楼】
  2. itest软件测试工具,Monkey测试工具 - iTest99的个人空间 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
  3. Neo4j 图数据科学应用 - 图目录和图投影(二)
  4. 计算机无法安装系统,电脑为什么重装不了系统?
  5. 从数据备份恢复来看,iCloud和iTunes到底有什么区别?
  6. Linux Regulator Framework(2) - regulator driver
  7. AndroidStudio报错Transform output file D:\android\RfidDemo\app\libs\RFID_lib.jar does not exist.
  8. 一文告诉你大数据是什么
  9. KL Divergence ——衡量两个概率分布之间的差异
  10. 班级主页效果图html,DW制作网页|html静态页面|班级网页素材|蝶恋花班级主页网站...