Files
massive-cloud/alg/平整度、平面度、轮廓测量v1.5/main.py
lipan 29f1d45d66 feat: 算法升级、整车配准集成与性能分析文档
算法更新: delivery v1.2.1、平整度v1.5、测距v2.2、整车配准v1.3
适配器: vehicle-registration 新增、各算法 manifest 和 adapter 更新
后端: taskCadFiles/source 字段迁移、derivedPointClouds 注册、取消任务联动
前端: ElapsedTime 时长显示、两步算法流程、canRun 逻辑修复
文档: 新增5份算法性能分析报告
2026-06-25 08:22:20 +00:00

207 lines
10 KiB
Python

from __future__ import annotations
import argparse
def build_parser() -> argparse.ArgumentParser:
common = argparse.ArgumentParser(add_help=False)
common.add_argument("--config", default=argparse.SUPPRESS, help="YAML config path, default uses built-in settings")
parser = argparse.ArgumentParser(description="Industrial geometry measurement workflow")
parser.add_argument("--config", default=None, help="YAML config path, default uses built-in settings")
subparsers = parser.add_subparsers(dest="command", required=True)
cad = subparsers.add_parser("cad2mesh", parents=[common], help="Convert STEP CAD to STL Mesh")
cad.add_argument("--cad", required=False, help="Input STEP file")
cad.add_argument("--mesh", required=False, help="Output STL file")
cad.add_argument("--precision", type=float, default=None, help="Mesh precision in mm")
denoise = subparsers.add_parser("denoise", parents=[common], help="Add noise and run denoise filters")
denoise.add_argument("--pointcloud", "-p", default=None, help="Input clean PLY point cloud")
denoise.add_argument("--noise-std", type=float, default=None, help="Gaussian noise std")
denoise.add_argument("--no-visualize", action="store_true", help="Disable Open3D windows")
registration = subparsers.add_parser("registration", parents=[common], help="Run simulated point-cloud registration")
registration.add_argument("--pointcloud", "-p", default=None, help="Input PLY point cloud")
registration.add_argument("--mesh", "-m", default=None, help="Reference STL/OBJ/PLY mesh")
registration.add_argument("--voxel-size", "-v", type=float, default=None, help="Registration voxel size")
registration.add_argument("--roll", type=float, default=None, help="Rotation around X axis in degrees")
registration.add_argument("--pitch", type=float, default=None, help="Rotation around Y axis in degrees")
registration.add_argument("--yaw", type=float, default=None, help="Rotation around Z axis in degrees")
registration.add_argument("--trans-range", type=float, default=None, help="Random translation range")
registration.add_argument("--no-visualize", action="store_true", help="Disable Open3D windows")
contour = subparsers.add_parser(
"contour",
parents=[common],
help="Quick contour/flatness/planarity evaluation against STEP CAD",
)
contour.add_argument("--pointcloud", "-p", default=None, help="Input PLY point cloud")
contour.add_argument("--cad", "-c", default=None, help="Reference STEP CAD file")
contour.add_argument("--mesh", "-m", default=None, help="Legacy reference STL/OBJ/PLY mesh")
contour.add_argument(
"--tasks",
default=None,
help="Comma-separated task ids or sample names. Example: 13 expands 13_1/13_2; 13_1 runs that sample only.",
)
contour.add_argument("--all", action="store_true", help="Run contour evaluation for all Mesh/CAD ids under data root")
contour.add_argument("--data-root", default="datasets", help="Dataset root for --tasks/--all batch mode")
contour.add_argument(
"--pointcloud-kind",
choices=["noise", "clean"],
default="noise",
help="Point cloud source for batch mode: noise=Noise_PointCloud, clean=PointCloud",
)
contour.add_argument("--mesh-deflection", type=float, default=None, help="CAD meshing deflection")
contour.add_argument("--point-chunk-size", type=int, default=None, help="Point chunk size")
contour.add_argument("--triangle-chunk-size", type=int, default=None, help="Triangle chunk size")
contour.add_argument("--save", default=None, help="Optional colored point-cloud output path")
contour.add_argument(
"--excel-output",
nargs="?",
const="excel/contour.xlsx",
default=None,
help="Optional Excel output path; defaults to excel/contour.xlsx when used without a value",
)
contour.add_argument(
"--result-template",
default="excel/测量结果.xlsx",
help="Measurement-result template used by --excel-output",
)
contour.add_argument(
"--combined-context-pointcloud",
default="datasets/train/train_2_10M.ply",
help="Full point cloud to include in batch combined_contour.ply",
)
contour.add_argument("--no-visualize", action="store_true", help="Disable Open3D windows")
curvature = subparsers.add_parser("curvature", parents=[common], help="Estimate and visualize point-cloud curvature")
curvature.add_argument("--pointcloud", "-p", default=None, help="Input PLY point cloud")
curvature.add_argument("--radius", type=float, default=None, help="Neighborhood radius")
curvature.add_argument("--max-nn", type=int, default=None, help="Max neighbor count")
curvature.add_argument("--color-scale", type=float, default=None, help="Color scale")
curvature.add_argument("--save", default=None, help="Optional colored point-cloud output path")
curvature.add_argument("--no-visualize", action="store_true", help="Disable Open3D windows")
plane = subparsers.add_parser("plane", parents=[common], help="Estimate plane with RANSAC")
plane.add_argument("--pointcloud", "-p", default=None, help="Optional input PLY point cloud")
plane.add_argument("--threshold-mm", type=float, default=None, help="RANSAC distance threshold in mm")
plane.add_argument("--max-iterations", type=int, default=None, help="RANSAC max iterations")
plane.add_argument("--no-visualize", action="store_true", help="Disable Open3D windows")
translate_align = subparsers.add_parser(
"translate-align",
parents=[common],
help="Translate-align point cloud to STEP CAD with front/tail centroids",
)
translate_align.add_argument("--cad", "-c", default="datasets/CAD/M02.stp", help="Reference STEP CAD file")
translate_align.add_argument(
"--pointcloud",
"-p",
default="datasets/shift_test_output/",
help="Input PLY point cloud or a directory containing shifted_whole_pointcloud.ply",
)
translate_align.add_argument("--output-dir", "-o", default="results", help="Output directory")
translate_align.add_argument("--axis", choices=["x", "y", "z"], default="x", help="Train length axis")
translate_align.add_argument("--crop-ratio", type=float, default=0.01, help="Front/tail crop ratio")
translate_align.add_argument("--mesh-deflection", type=float, default=0.1, help="CAD meshing deflection")
translate_align.add_argument("--cad-sample-points", type=int, default=30000, help="Points sampled from CAD mesh")
translate_align.add_argument("--local-sample-points", type=int, default=1000, help="Points sampled from each end")
translate_align.add_argument("--scale-pointcloud", type=float, default=1.0, help="Scale factor applied to point cloud")
translate_align.add_argument("--no-visualize", action="store_true", help="Disable Open3D windows")
full = subparsers.add_parser("full", parents=[common], help="Run configured full workflow")
full.add_argument("--no-visualize", action="store_true", help="Disable Open3D windows")
return parser
def main() -> None:
parser = build_parser()
args = parser.parse_args()
from pipeline import MeasurementPipeline
pipeline = MeasurementPipeline(config_path=args.config)
if args.command == "cad2mesh":
pipeline.run_cad2mesh(cad_path=args.cad, mesh_path=args.mesh, precision=args.precision)
elif args.command == "denoise":
pipeline.run_denoise(pointcloud_path=args.pointcloud, noise_std=args.noise_std, no_visualize=args.no_visualize)
elif args.command == "registration":
pipeline.run_registration(
pointcloud_path=args.pointcloud,
mesh_path=args.mesh,
voxel_size=args.voxel_size,
roll=args.roll,
pitch=args.pitch,
yaw=args.yaw,
trans_range=args.trans_range,
no_visualize=args.no_visualize,
)
elif args.command == "contour":
if args.all or args.tasks:
pipeline.run_contour_batch(
task_ids=args.tasks,
all_tasks=args.all,
data_root=args.data_root,
pointcloud_kind=args.pointcloud_kind,
mesh_deflection=args.mesh_deflection,
point_chunk_size=args.point_chunk_size,
triangle_chunk_size=args.triangle_chunk_size,
save_path=args.save,
excel_output_path=args.excel_output,
result_template_path=args.result_template,
combined_context_pointcloud_path=args.combined_context_pointcloud,
no_visualize=args.no_visualize,
)
else:
pipeline.run_contour(
pointcloud_path=args.pointcloud,
cad_path=args.cad,
mesh_path=args.mesh,
mesh_deflection=args.mesh_deflection,
point_chunk_size=args.point_chunk_size,
triangle_chunk_size=args.triangle_chunk_size,
save_path=args.save,
excel_output_path=args.excel_output,
result_template_path=args.result_template,
no_visualize=args.no_visualize,
)
elif args.command == "curvature":
pipeline.run_curvature(
pointcloud_path=args.pointcloud,
radius=args.radius,
max_nn=args.max_nn,
color_scale=args.color_scale,
save_path=args.save,
no_visualize=args.no_visualize,
)
elif args.command == "plane":
pipeline.run_plane(
pointcloud_path=args.pointcloud,
threshold_mm=args.threshold_mm,
max_iterations=args.max_iterations,
no_visualize=args.no_visualize,
)
elif args.command == "translate-align":
pipeline.run_translate_align_pointcloud_to_cad(
cad_path=args.cad,
pointcloud_path=args.pointcloud,
output_dir=args.output_dir,
axis=args.axis,
crop_ratio=args.crop_ratio,
mesh_deflection=args.mesh_deflection,
cad_sample_points=args.cad_sample_points,
local_sample_points=args.local_sample_points,
scale_pointcloud=args.scale_pointcloud,
no_visualize=args.no_visualize,
)
elif args.command == "full":
pipeline.run_full(no_visualize=args.no_visualize)
else:
parser.error(f"Unsupported command: {args.command}")
if __name__ == "__main__":
main()