Compare commits

...

7 Commits

Author SHA1 Message Date
mckay 77c4e0dc37 feat: Add configurable CSV output filename for evaluation results 4 months ago
mckay 5a708af310 docs: preprocess readme 4 months ago
mckay 46eae8e02d fix refactor 4 months ago
mckay 13617025ac director separate 4 months ago
mckay e4b6a7b47f docs:Enhance normalization process in Source.cpp for mesh vertices 5 months ago
mckay 8940f83fcc Add FeatureSampleConfig class for command line configuration parsing 5 months ago
mckay a443756499 Enhance idea.md with new research points and implementation suggestions; add Dockerfile and .gitignore for pre-processing setup 5 months ago
  1. 5
      code/evaluation/evaluation.py
  2. 3
      code/pre_processing/.gitignore
  3. 23
      code/pre_processing/Dockerfile
  4. 94
      code/pre_processing/FeatureSample/FeatureSampleConfig.cpp
  5. 48
      code/pre_processing/FeatureSample/FeatureSampleConfig.h
  6. 1671
      code/pre_processing/FeatureSample/Source.cpp
  7. 52
      code/pre_processing/README.md
  8. 20
      idea.md

5
code/evaluation/evaluation.py

@ -30,6 +30,7 @@ parser.add_argument('--pred_path', type=str,
parser.add_argument('--name_list', type=str, default='broken_bullet_name.txt', help='names of models to be evaluated, if you want to evaluate the whole dataset, please set it as all_names.txt') parser.add_argument('--name_list', type=str, default='broken_bullet_name.txt', help='names of models to be evaluated, if you want to evaluate the whole dataset, please set it as all_names.txt')
parser.add_argument('--nsample', type=int, default=50000, help='point batch size') parser.add_argument('--nsample', type=int, default=50000, help='point batch size')
parser.add_argument('--regen', default = False, action="store_true", help = 'regenerate feature curves') parser.add_argument('--regen', default = False, action="store_true", help = 'regenerate feature curves')
parser.add_argument('--csv_name', type=str, default='eval_results.csv', help='csv file name')
args = parser.parse_args() args = parser.parse_args()
def distance_p2p(points_src, normals_src, points_tgt, normals_tgt): def distance_p2p(points_src, normals_src, points_tgt, normals_tgt):
@ -230,9 +231,9 @@ def compute_all():
# 保存结果 # 保存结果
df = pd.DataFrame(results) df = pd.DataFrame(results)
df.to_csv('eval_results.csv', index=False) df.to_csv(args.csv_name, index=False)
logger.info(f"Evaluation completed. Results saved to {os.path.abspath('eval_results.csv')}") logger.info(f"Evaluation completed. Results saved to {os.path.abspath(args.csv_name)}")
except Exception as e: except Exception as e:
logger.error(f"Error in compute_all: {str(e)}") logger.error(f"Error in compute_all: {str(e)}")

3
code/pre_processing/.gitignore

@ -0,0 +1,3 @@
training_data/
raw_input/
Bin/

23
code/pre_processing/Dockerfile

@ -0,0 +1,23 @@
# 基础版本
FROM ubuntu:20.04
# 基本设置
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Asia/Shanghai
# 安装基础包
RUN apt-get update && apt-get install -y \
build-essential \
cmake \
python3 \
python3-pip \
libboost-all-dev \
git \
vim \
&& rm -rf /var/lib/apt/lists/*
# 工作目录
WORKDIR /app
# 启动终端
CMD ["/bin/bash"]

94
code/pre_processing/FeatureSample/FeatureSampleConfig.cpp

@ -0,0 +1,94 @@
#include "FeatureSampleConfig.h"
#include <iostream>
namespace MeshLib {
FeatureSampleConfig FeatureSampleConfig::FromCommandLine(int argc, char** argv) {
cxxopts::Options options("FeatureSample", "Feature sampling for 3D meshes");
options.add_options()
("i,input", "input mesh (obj/off format)", cxxopts::value<std::string>())
("f,feature", "input feature file (fea format)", cxxopts::value<std::string>())
("p,pointcloud", "input pointcloud", cxxopts::value<std::string>())
("pf", "face of input pointcloud", cxxopts::value<std::string>())
("o,output", "output mesh/points", cxxopts::value<std::string>())
("k,mask", "output mask file", cxxopts::value<std::string>())
("fs", "feature samples", cxxopts::value<int>())
("ns", "non-feature samples", cxxopts::value<int>())
("m,mode", "processing mode", cxxopts::value<int>())
("c,color", "use coloring", cxxopts::value<int>())
("mp", "max patches per cluster", cxxopts::value<int>())
("cot", "use cotangent weight", cxxopts::value<int>())
("s,sigma", "position noise sigma", cxxopts::value<double>())
("sn", "normal noise sigma", cxxopts::value<double>())
("csg", "generate csg tree", cxxopts::value<int>())
("convex", "is first layer convex", cxxopts::value<int>())
("r,repairturn", "repair turn vertex", cxxopts::value<int>())
("verbose", "verbose level", cxxopts::value<int>())
("strict", "strict mode")
("repairtree", "repair tree feature")
("h,help", "print help");
auto result = options.parse(argc, argv);
if (result.count("help")) {
std::cout << options.help() << std::endl;
exit(0);
}
FeatureSampleConfig config;
// 检查必需参数
if (!result.count("m") || !result.count("i") || !result.count("o")) {
throw std::runtime_error("Missing required parameters");
}
// 设置文件路径
config.files.input_mesh = result["i"].as<std::string>();
config.files.output_file = result["o"].as<std::string>();
if (result.count("f")) config.files.input_feature = result["f"].as<std::string>();
if (result.count("p")) config.files.input_pointcloud = result["p"].as<std::string>();
if (result.count("pf")) config.files.input_pointcloud_face = result["pf"].as<std::string>();
if (result.count("k")) config.files.output_mask = result["k"].as<std::string>();
// 设置采样参数
if (result.count("fs")) config.sampling.feature_samples = result["fs"].as<int>();
if (result.count("ns")) config.sampling.nonfeature_samples = result["ns"].as<int>();
if (result.count("s")) config.sampling.sigma = result["s"].as<double>();
if (result.count("sn")) config.sampling.sigma_normal = result["sn"].as<double>();
if (result.count("cot")) config.sampling.use_cotweight = result["cot"].as<int>();
// 设置处理选项
config.processing.mode = result["m"].as<int>();
if (result.count("c")) config.processing.use_color = result["c"].as<int>();
if (result.count("mp")) config.processing.max_patches = result["mp"].as<int>();
if (result.count("csg")) config.processing.generate_csg = result["csg"].as<int>();
if (result.count("convex")) config.processing.is_convex = result["convex"].as<int>();
if (result.count("r")) config.processing.repair_turn = result["r"].as<int>();
if (result.count("verbose")) config.processing.verbose = result["verbose"].as<int>();
if (result.count("strict")) config.processing.strict_mode = true;
if (result.count("repairtree")) config.processing.repair_tree = true;
return config;
}
bool FeatureSampleConfig::Validate() const {
// 检查文件路径
if (files.input_mesh.empty() || files.output_file.empty()) {
return false;
}
// 检查采样参数
if (sampling.feature_samples < 0 || sampling.nonfeature_samples < 0) {
return false;
}
// 检查处理模式
if (processing.mode != 0 && processing.mode != 1) {
return false;
}
return true;
}
} // namespace MeshLib

48
code/pre_processing/FeatureSample/FeatureSampleConfig.h

@ -0,0 +1,48 @@
#pragma once
#include <string>
#include "cxxopts.hpp"
namespace MeshLib {
class FeatureSampleConfig {
public:
// 文件路径
struct FilePaths {
std::string input_mesh; // 输入网格文件
std::string input_feature; // 输入特征文件
std::string input_pointcloud; // 输入点云文件
std::string input_pointcloud_face; // 输入点云面片文件
std::string output_file; // 输出文件
std::string output_mask; // 输出掩码文件
} files;
// 采样参数
struct SamplingParams {
int feature_samples = 10000; // 特征边采样点数
int nonfeature_samples = 40000; // 非特征面采样点数
double sigma = 0.0; // 位置噪声标准差
double sigma_normal = 0.0; // 法向噪声标准差
bool use_cotweight = false; // 是否使用余切权重
} sampling;
// 处理选项
struct ProcessingOptions {
int mode = 1; // 处理模式 (0:标准化, 1:特征采样)
bool use_color = false; // 是否使用颜色
int max_patches = -1; // 每个颜色簇的最大面片数
bool generate_csg = false; // 是否生成CSG树
bool is_convex = false; // 第一层是否为凸的
bool repair_turn = true; // 是否修复转角顶点
bool repair_tree = false; // 是否修复树特征
bool strict_mode = false; // 是否使用严格模式
int verbose = 0; // 详细输出级别
} processing;
// 从命令行参数解析配置
static FeatureSampleConfig FromCommandLine(int argc, char** argv);
// 验证配置是否有效
bool Validate() const;
};
} // namespace MeshLib

1671
code/pre_processing/FeatureSample/Source.cpp

File diff suppressed because it is too large

52
code/pre_processing/README.md

@ -10,11 +10,15 @@ Please first download the prepared ABC dataset from [BaiduYun](https://pan.baidu
**\[Optional\]** If you want to split the models and generate the correponding *.fea files from the raw ABC dataset, please first put the *.yml and *.obj files in folder _abc_data_ (make sure that file in different formats share the same prefix). Install the PyYAML package via: **\[Optional\]** If you want to split the models and generate the correponding *.fea files from the raw ABC dataset, please first put the *.yml and *.obj files in folder _abc_data_ (make sure that file in different formats share the same prefix). Install the PyYAML package via:
$ pip install PyYAML ```
$ pip install PyYAML
```
and run: and run:
$ python split_and_gen_fea.py ```
$ python split_and_gen_fea.py
```
You will find the split models and *.fea files in _raw_input_. You will find the split models and *.fea files in _raw_input_.
@ -22,39 +26,55 @@ You will find the split models and *.fea files in _raw_input_.
Please first install the Boost and eigen3 library: Please first install the Boost and eigen3 library:
$ sudo apt install libboost-all-dev ```
$ sudo apt install libeigen3-dev $ sudo apt install libboost-all-dev
$ sudo apt install libeigen3-dev
```
Then run: Then run:
$ cd PATH_TO_NH-REP/code/pre_processing ```
$ mkdir build && cd build $ cd PATH_TO_NH-REP/code/pre_processing
$ cmake .. $ mkdir build && cd build
$ make $ cmake ..
$ make
```
You can generate the training data: You can generate the training data:
$ cd .. ```
$ python gen_training_data_yaml.py $ cd ..
$ python gen_training_data_yaml.py
```
The generated training data can be found in _training_data_ folder. The generated training data can be found in _training_data_ folder.
If you do not have a yaml file and want to generate sample points from meshes, you can prepare the *.fea file as sharp feature curves of the meshes, then run: If you do not have a yaml file and want to generate sample points from meshes, you can prepare the *.fea file as sharp feature curves of the meshes, then run:
$ python gen_training_data_mesh.py ```
$ python gen_training_data_mesh.py
```
Please make sure that you set 'in_path' in _gen_training_data_yaml.py_ and _gen_training_data_mesh.py_ as the path containing the *.fea files. Please make sure that you set 'in_path' in _gen_training_data_yaml.py_ and _gen_training_data_mesh.py_ as the path containing the *.fea files.
When patch decomposition is conducted (like model 00007974_5), there will be *fixtree.obj and *fixtree.fea in _training_data_, which can be used for generating point samples in later round: When patch decomposition is conducted (like model 00007974_5), there will be *fixtree.obj and *fixtree.fea in _training_data_, which can be used for generating point samples in later round:
$ python gen_training_data_yaml.py -r ```
$ python gen_training_data_yaml.py -r
```
or
or ```
$ python gen_training_data_mesh.py -r
```
$ python gen_training_data_mesh.py -r
You can find the generated training data of the decomposed patch in _training_data_repair_. By default we only decompose one patch and it is enough for most models. But if you find *fixtree.obj and *fixtree.fea in _training_data_repair_, that means that more patches need to decomposed. There are two ways to achieve this. First, you can copy _training_data_repair./*fixtree.obj_ and _training_data_repair./*fixtree.fea_ to _training_data_, and re-run 'python gen_training_data_yaml.py -r', until enough patches are decomposed (i.e. *.conf files can be found in _training_data_repair_). Another way is to decompose all patches at once, to achieve this, simple uncomment the following line in _FeatureSample/helper.cpp_: You can find the generated training data of the decomposed patch in _training_data_repair_. By default we only decompose one patch and it is enough for most models. But if you find *fixtree.obj and *fixtree.fea in _training_data_repair_, that means that more patches need to decomposed. There are two ways to achieve this. First, you can copy _training_data_repair./*fixtree.obj_ and _training_data_repair./*fixtree.fea_ to _training_data_, and re-run 'python gen_training_data_yaml.py -r', until enough patches are decomposed (i.e. *.conf files can be found in _training_data_repair_). Another way is to decompose all patches at once, to achieve this, simple uncomment the following line in _FeatureSample/helper.cpp_:
https://github.com/guohaoxiang/NH-Rep/blob/42ae22bf8fc3f1b4f9f5592443c29aafe86905bd/code/pre_processing/FeatureSample/helper.cpp#L722 https://github.com/guohaoxiang/NH-Rep/blob/42ae22bf8fc3f1b4f9f5592443c29aafe86905bd/code/pre_processing/FeatureSample/helper.cpp#L722
After that, rebuild the executable files, and re-run 'python gen_training_data_yaml.py' and 'python gen_training_data_yaml.py -r'. There will be generated training data in _training_data_repair_. After that, rebuild the executable files, and re-run 'python gen_training_data_yaml.py' and 'python gen_training_data_yaml.py -r'. There will be generated training data in _training_data_repair_.
docker build -t brep_pre_processing:v1 .
docker run -it --name brep_processor -v ~/NH-Rep/code/pre_processing:/app brep_pre_processing:v1

20
idea.md

@ -3,29 +3,35 @@
## 1. 数据噪声鲁棒性增强 ## 1. 数据噪声鲁棒性增强
### 研究问题 ### 研究问题
现有的方法对数据噪声有一定的鲁棒性,但仍有改进空间。研究如何进一步提高算法对噪声的鲁棒性。 现有的方法对数据噪声有一定的鲁棒性,但仍有改进空间。研究如何进一步提高算法对噪声的鲁棒性。
### 创新点 ### 创新点
- **噪声建模**:引入更复杂的噪声模型(高斯噪声、椒盐噪声等),测试算法在不同噪声条件下的表现 - **噪声建模**:引入更复杂的噪声模型(高斯噪声、椒盐噪声等),测试算法在不同噪声条件下的表现
- **对抗训练**:使用对抗生成网络(GAN)或自监督学习方法,增强模型对噪声的鲁棒性 - **对抗训练**:使用对抗生成网络(GAN)或自监督学习方法,增强模型对噪声的鲁棒性
- **正则化技术**:探索新的正则化方法(平滑损失、总变差正则化等),减少噪声对模型的影响 - **正则化技术**:探索新的正则化方法(平滑损失、总变差正则化等),减少噪声对模型的影响
- **多尺度处理**:结合多尺度分析,处理不同层次的几何细节,提高对局部噪声的鲁棒性 - **多尺度处理**:结合多尺度分析,处理不同层次的几何细节,提高对局部噪声的鲁棒性
### 预期成果 ### 预期成果
开发一种更鲁棒的隐式转换方法,能够在存在噪声的情况下保持较高的转换质量。 开发一种更鲁棒的隐式转换方法,能够在存在噪声的情况下保持较高的转换质量。
## 2. 特征保留与细节增强 ## 2. 特征保留与细节增强
### 研究问题 ### 研究问题
虽然现有的方法在保留尖锐特征方面表现出色,但仍然有提升空间。研究如何更好地捕捉和保留B-Rep模型中的细小特征。 虽然现有的方法在保留尖锐特征方面表现出色,但仍然有提升空间。研究如何更好地捕捉和保留B-Rep模型中的细小特征。
### 创新点 ### 创新点
- **特征检测改进**:引入更先进的特征检测算法(基于深度学习的边缘检测、曲率估计等) - **特征检测改进**:引入更先进的特征检测算法(基于深度学习的边缘检测、曲率估计等)
- **特征增强损失**:设计专门针对特征保留的损失函数(如特征角度误差FAE的加权版本) - **特征增强损失**:设计专门针对特征保留的损失函数(如特征角度误差FAE的加权版本)
- **多分辨率表示**:结合多分辨率表示方法,动态调整特征区域的采样密度 - **多分辨率表示**:结合多分辨率表示方法,动态调整特征区域的采样密度
- **后处理优化**:研究等值面提取后的后处理方法,增强特征的清晰度和准确性 - **后处理优化**:研究等值面提取后的后处理方法,增强特征的清晰度和准确性
### 预期成果 ### 预期成果
提出一种能够在保持整体几何精度的同时,更好保留尖锐特征和细节的隐式转换方法。 提出一种能够在保持整体几何精度的同时,更好保留尖锐特征和细节的隐式转换方法。
[... 其他部分类似格式 ...] [... 其他部分类似格式 ...]
@ -33,26 +39,30 @@
# 实施建议 # 实施建议
1. **选择具体切入点** 1. **选择具体切入点**
- 根据兴趣和资源选择研究重点 - 根据兴趣和资源选择研究重点
- 每个方向都有其独特的挑战和机遇 - 每个方向都有其独特的挑战和机遇
2. **文献综述** 2. **文献综述**
- 进行广泛的文献综述 - 进行广泛的文献综述
- 了解当前研究进展和存在的问题 - 了解当前研究进展和存在的问题
- 找到研究空白点 - 找到研究空白点
3. **实验设计** 3. **实验设计**
- 设计合理的实验方案 - 设计合理的实验方案
- 选择合适的数据集 - 选择合适的数据集
- 设定评估指标 - 设定评估指标
- 搭建实验环境 - 搭建实验环境
4. **代码实现** 4. **代码实现**
- 使用合适的编程工具(Python、PyTorch、TensorFlow等) - 使用合适的编程工具(Python、PyTorch、TensorFlow等)
- 参考开源项目 - 参考开源项目
- 确保代码原创性 - 确保代码原创性
5. **论文撰写** 5. **论文撰写**
- 撰写详细的毕业论文 - 撰写详细的毕业论文
- 包含完整的研究内容 - 包含完整的研究内容
- 突出创新点和贡献 - 突出创新点和贡献
1.15

Loading…
Cancel
Save