当前位置: 首页 > news >正文

C++ Eigen最小二乘拟合三维直线

1. 基本类型

    /*** @brief 线*/struct Line3d {Eigen::Vector3d point {};Eigen::Vector3d direction {};};

2. 拟合结果可为空类型宏定义,用于std::optional与boost::optional平替


#ifdef OPTIONAL_BOOST
#include <boost/optional.hpp>
#ifndef M_OPTIONAL
#define M_OPTIONAL M_OPTIONAL
#endif // !M_OPTIONAL#ifndef OPTIONAL_NONE
#define OPTIONAL_NONE boost::none
#endif // !OPTIONAL_NONE
#else
#include <optional>
#ifndef M_OPTIONAL
#define M_OPTIONAL std::optional
#endif // !M_OPTIONAL#ifndef OPTIONAL_NONE
#define OPTIONAL_NONE std::nullopt
#endif // !OPTIONAL_NONE
#endif // !OPTIONAL_BOOST

3. 三维直线拟合函数

M_OPTIONAL<Line3d> FitLine3dPCA(const std::vector<Eigen::Vector3d>& points)
{if (points.size() < 2) {return { OPTIONAL_NONE };}// 计算质心Eigen::Vector3d centroid = Eigen::Vector3d::Zero();for (const auto& p : points) {centroid += p;}centroid /= points.size();// 构建协方差矩阵Eigen::Matrix3d cov = Eigen::Matrix3d::Zero();for (const auto& p : points) {Eigen::Vector3d centered = p - centroid;cov += centered * centered.transpose();}cov /= points.size();// 求协方差矩阵的特征向量(最大特征值对应的方向)Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> solver(cov);if (solver.info() != Eigen::Success) {return { OPTIONAL_NONE };}Eigen::Vector3d direction = solver.eigenvectors().col(2).normalized();Line3d line;line.point = centroid;line.direction = direction;return line;
}

4. 读取点文件工具函数

4.1. 点格式示例

1,3.3430063665158043,-2.2194078290652977,0.3354974815183671
2,1.7449288088835502,-0.8618028071806091,4.60509480423679
3,0.7857717528889129,-0.40685814532015363,-0.3132400527103719
4,0.4627448446856639,2.5927289953742285,2.009015614598561
5,3.3417530022332964,1.2860073754736252,2.8298107704812754
6,2.991151484336692,4.202162573792802,3.8695985120956156
7,1.0810646673514561,5.491595123760361,1.264199175914956
8,4.9517287623536,5.930930911561477,3.4499954792885714
9,-1.6884482187454348,3.841324915056982,3.6498221054770283
10,1.1753280668817334,1.9011403492990624,2.0105584013510045

4.2. 读取函数实现,这里以Qt为例

std::vector<Eigen::Vector3d> ReadXYZs(const QString& path)
{QFile file(path);if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {qDebug() << "Open file failed!";return {};}std::vector<Eigen::Vector3d> points;{QTextStream in(&file);while (!in.atEnd()) {QString line = in.readLine();QStringList list = line.split(",");if (list.size() != 4) {continue;}points.push_back({ list[1].toDouble(), list[2].toDouble(), list[3].toDouble() });}file.close();qDebug() << "point count:" << points.size();}return points;
}

5. 拟合示例

int main(int argc, char* argv[])
{auto&& points = ReadXYZs(":/data/perturbed_line_points.csv");auto&& t = FitLine3dPCA(points);if (!t.has_value()) {qDebug() << "拟合失败";return 0;}auto&& line = t.value();std::cout << "\n\nFitLine3dPCA:\n"<< "point: (" << line.point.transpose() << ")\n"<< "direction: (" << line.direction.transpose() << ")\n\n\n";return 0;
}

6. 拟合结果

在这里插入图片描述

http://www.dtcms.com/a/318231.html

相关文章:

  • KMP-next数组详解
  • sigaction结构体详解
  • 推荐一款优质的开源博客与内容管理系统
  • 集团敏捷组织转型项目研讨材料(105页PPT)精品
  • Mac安装WebStorm for Mac v2025.1.1
  • PDF注释的加载和保存的实现
  • Enhancing Long Video Question Answering with Scene-Localized Frame Grouping
  • python中的推导式
  • Android PDFBox 的使用指南
  • 力扣热题100------136.只出现一次的数字
  • 【纵火犯的春天】纵火犯是如何解题leetcode的?
  • Python驱动的无人机多光谱-点云融合技术在生态三维建模与碳储量/生物量/LULC估算中的全流程实战
  • JDK9+ Method.class.getDeclaredFields() Method实例将不能再直接通过反射修改
  • 无人机航拍数据集|第4期 无人机太阳光伏板红外目标检测YOLO数据集10945张yolov11/yolov8/yolov5可训练
  • 大疆无人机使用eport连接Jetson主板实现目标检测
  • selenium操作指南
  • 前端路由守卫
  • JavaWeb服务器/servlet容器(Tomcat、Undertow 、WebLogic)
  • 前端应用场景题目(待总结优化)
  • 攻防世界WEB(新手模式)20-unseping
  • 基于 kubeadm 搭建 k8s 集群
  • 京东商品评论接口开发全指南:从数据获取到分析应用实战
  • 【20205CVPR-目标检测方向】基于事件的高效目标检测:具有空间和时间注意力的混合神经网络
  • Lodash 的终极进化Radashi
  • JAVA 程序员cursor 和idea 结合编程
  • 北京JAVA基础面试30天打卡03
  • SAP MR51 显示不是ALV格式的问题
  • 开源远程工具rustdesk
  • 力扣 hot100 Day67
  • Linux firewall 防火墙管理