基于随机抽样或最小二乘法 c++实现三维点云平面检测

随机抽样

std::vector<int> random(int n, int N){std::vector<int> rets;for(int i=0; i<N; i++){while(true){int v = rand() % n;if(std::find(rets.begin(), rets.end(), v) == rets.end()){rets.push_back(v);break;}}}return rets;
}
bool Plane(std::vector<cv::Point3f>& cloud, std::vector<cv::Point3f>& cloudPlane){int nPlane = xxx;float thred = xxx;float P = xxx;int Iter = xxx;int S = Iter;int N = xxx;int n = cloud.size();if(n < nPlane){std::cout<<"not enough points"<<std::endl;return false;}int iter = 0;std::vector<int> inliersBest;while(true){iter++;std::vector<int> index = random(n, N);cv::Mat A = cv::Mat(3, 3, CV_32F);cv::Mat b = cv::Mat(3, 1, CV_32F);A.at<float>(0, 0) = cloud[index[0]].x;A.at<float>(0, 1) = cloud[index[0]].y;A.at<float>(0, 2) = cloud[index[0]].z;A.at<float>(1, 0) = cloud[index[1]].x;A.at<float>(1, 1) = cloud[index[1]].y;A.at<float>(1, 2) = cloud[index[1]].z;A.at<float>(2, 0) = cloud[index[2]].x;A.at<float>(2, 1) = cloud[index[2]].y;A.at<float>(2, 2) = cloud[index[2]].z;b.at<float>(0, 0) = -1;b.at<float>(1, 0) = -1;b.at<float>(2, 0) = -1;b = A.t() * b;A = A.t() * A;if(cv::determinant(A) == 0) continue;cv::Mat normal = A.inv() * b;if(cv::norm(normal) == 0) continue;std::vector<int> inliers;for(int i=0; i<n; i++){float distance = std::abs(normal.at<float>(0, 0)*cloud[i].x + normal.at<float>(1, 0)*cloud[i].y + normal.at<float>(2, 0)*cloud[i].z + 1) / cv::norm(normal);if(distance < thred) inliers.push_back(i);}if(inliers.size() > inliersBest.size()){inliersBest = inliers;float p = float(inliers.size()) / n;S = std::log(1-P)/std::log(1 - std::pow(p, N));}if(iter > Iter || iter > S) break;}cv::Mat A = cv::Mat(inliersBest.size(), 3, CV_32F);cv::Mat b = cv::Mat(inliersBest.size(), 1, CV_32F);for(int i=0; i<inliersBest.size(); i++){A.at<float>(i, 0) = cloud[inliersBest[i]].x;A.at<float>(i, 1) = cloud[inliersBest[i]].y;A.at<float>(i, 2) = cloud[inliersBest[i]].z;b.at<float>(i, 0) = -1;}b = A.t() * b;A = A.t() * A;if(cv::determinant(A) == 0){std::cout<<"zero determinant"<<std::endl;return false;}cv::Mat normal = A.inv() * b;if(cv::norm(normal) == 0){std::cout<<"zero normal"<<std::endl;return false;}for(int i=0; i<cloud.size(); i++){float distance = std::abs(normal.at<float>(0, 0)*cloud[i].x + normal.at<float>(1, 0)*cloud[i].y + normal.at<float>(2, 0)*cloud[i].z + 1) / cv::norm(normal);if(distance < thred) cloudPlane.push_back(cloud[i]);}if(cloudPlane.size() < nPlane){std::cout<<"not enough plane points"<<std::endl;return false;}return true;
}

最小二乘法:最小二乘法原理

bool Plane(vector<cv::Point3f> cloud, double& a, double& b, double& c, double& angle)
{double A11 = 0, A12 = 0, A13 = 0;double A21 = 0, A22 = 0, A23 = 0;double A31 = 0, A32 = 0, A33 = 0;double B1 = 0, B2 = 0, B3 = 0;for (int i = 0; i < cloud.size(); i++){A11 += cloud.at(i).x*cloud.at(i).x;A12 += cloud.at(i).x*cloud.at(i).y;A13 += cloud.at(i).x;A21 += cloud.at(i).x*cloud.at(i).y;A22 += cloud.at(i).y*cloud.at(i).y;A23 += cloud.at(i).y;A31 += cloud.at(i).x;A32 += cloud.at(i).y;B1 += cloud.at(i).x*cloud.at(i).z;B2 += cloud.at(i).y*cloud.at(i).z;B3 += cloud.at(i).z;}A33 = cloud.size();cv::Mat A(3, 3, CV_32FC1);A.at<float>(0, 0) = A11; A.at<float>(0, 1) = A12; A.at<float>(0, 2) = A13;A.at<float>(1, 0) = A21; A.at<float>(1, 1) = A22; A.at<float>(1, 2) = A23;A.at<float>(2, 0) = A31; A.at<float>(2, 1) = A32; A.at<float>(2, 2) = A33;cv::Mat B(3, 1, CV_32FC1);B.at<float>(0, 0) = B1; B.at<float>(1, 0) = B2; B.at<float>(2, 0) = B3;cv::Mat X;X = A.inv()*B;                                                              //X为3*1解向量,分别对应平面方程z=ax+by+c中的abca = X.at<float>(0, 0);b = X.at<float>(1, 0);c = X.at<float>(2, 0);// 计算平面的法向量Eigen::Vector3d normal_vector(a, b, c);normal_vector.normalize();// 计算相对于水平面的角度angle = std::acos(normal_vector.dot(Eigen::Vector3d(0, 0, 1))) * 180.0 / M_PI;  // Eigen::Vector3d(0, 0, 1)水平面法向量return true;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/620067.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据安全保障的具体措施有哪些

随着信息化时代的到来&#xff0c;数据已经成为企业和社会发展的重要资产。然而&#xff0c;数据安全问题也日益突出&#xff0c;如何保障数据的安全性、完整性和可用性成为了亟待解决的问题。以下将详细探讨数据安全保障的各个方面&#xff0c;以期为企业和社会提供更好的数据…

飞桨分子动力学模拟-论文复现第六期:复现TorchMD

飞桨分子动力学模拟-论文复现第六期&#xff1a;复现TorchMD Paddle for MD 飞桨分子动力学模拟科学计算 复现论文-TorchMD: A deep learning framework for molecular simulations 本项目可在AIStudio一键运行&#xff1a;飞桨分子动力学模拟PaddleMD-复现TorchMD 【论文复…

分布式系统的前世

文章目录 前言分布式系统解决了什么问题分布式系统存在什么问题总结 前言 大家好&#xff0c;我是醉墨居士&#xff0c;我准备和大家浅聊一下分布式系统&#xff0c;分享我一下我的心得体会&#x1fae0; 分布式系统解决了什么问题 如果用户的请求压力过于庞大&#xff0c;使…

原生Ajax的使用,四种请求方法示例(前后端代码)

目录 原生Ajax是什么 原生Ajax的优点 Ajax应用环境 Ajax的使用 基本使用步骤 AJAX请求状态和HTTP状态码 AJAX 请求状态 HTTP 状态码 XHR对象的方法 各种请求方式和数据获取 post请求 post 请求完整代码 get 请求 服务端 put 请求 服务端 delete 请求 服务端代…

TypeScript基础知识:类型守卫和类型推断

在 TypeScript 中&#xff0c;类型守卫和类型推断是两个重要的概念&#xff0c;它们可以帮助我们更好地理解和利用类型系统的优势。本文将详细介绍这两个概念&#xff0c;并提供示例代码来说明它们的用法和优势。 一、类型守卫 类型守卫是一种在 TypeScript 中用于缩小变量类型…

U盘安装XP纯净版系统教程软件安装教程(附软件下载地址)

软件简介&#xff1a; 软件【下载地址】获取方式见文末。注&#xff1a;推荐使用&#xff0c;更贴合此安装方法&#xff01; U盘安装XP纯净版系统是一种便捷且快速的方式&#xff0c;以实现系统重装或升级的需求。这篇教程将为您详细介绍如何使用U盘来安装XP纯净版系统。XP纯…

代码随想录Day 17 | 110 平衡二叉树 257 二叉树的所有路径 404 左叶子之和

代码随想录Day 17 | 110 平衡二叉树 257 二叉树的所有路径 404 左叶子之和 平衡二叉树二叉树的所有路径左叶子之和 平衡二叉树 文档讲解&#xff1a;代码随想录 视频讲解&#xff1a; 后序遍历求高度&#xff0c;高度判断是否平衡 | LeetCode&#xff1a;110.平衡二叉树 状态 …

DEJA_VU3D - Cesium功能集 之 117-雷达扫描(圆环效果)

前言 编写这个专栏主要目的是对工作之中基于Cesium实现过的功能进行整合,有自己琢磨实现的,也有参考其他大神后整理实现的,初步算了算现在有差不多实现小140个左右的功能,后续也会不断的追加,所以暂时打算一周2-3更的样子来更新本专栏(每篇博文都会奉上完整demo的源代码…

C++知识点总结(13):函数

一、定义 函数&#xff0c;指可以实现某个功能&#xff0c;可以重复使用的一段代码。不同的函数之间相互独立&#xff0c;即函数之间的功能互不影响&#xff08;互相的代码&#xff09;。 二、结构 1. 定义 返回值类型 函数名(形参1, 形参2, 形参3...形参n) {...return 值; }2…

Java初学习

Java代码示例&#xff1a; public class helloworld {public static void main(String[] args){System.out.println("hello world");} } Java程序的名字需要和文件名字一致&#xff0c;就是那个helloworld Java程序需要对类有深度的认识&#xff1a; 对象是类的…

2023年全国职业院校技能大赛软件测试赛题—单元测试卷②

单元测试 一、任务要求 题目1&#xff1a;任意输入2个正整数值分别存入x、y中&#xff0c;据此完成下述分析&#xff1a;若x≤0或y≤0&#xff0c;则提示&#xff1a;“输入不符合要求。”&#xff1b;若2值相同&#xff0c;则提示“可以构建圆形或正方形”&#xff1b;若2<…

ipad协议逆向分析实战篇-1

请使用dnspy环境进行学习研究&#xff0c;切勿用于非法操作 1.首先拿到得到的部署包进行逆向分析 2.解压部署包并找到bin这个文件夹 3.找到Wechat.Api.dll这个文件 4.这两个是协议的核心文件&#xff0c;破解了这个核心文件就可以得出逻辑源码 5.首先把Wechat.Api.dll这个…

Pandas实战100例 | 案例 23: 处理空值

案例 23: 处理空值 知识点讲解 处理空值是数据清洗过程中的一个关键步骤。Pandas 提供了多种方法来检测、填充和删除空值。 检测空值: 使用 isnull 方法可以检测 DataFrame 中的空值。填充空值: 使用 fillna 方法可以填充空值。删除包含空值的行或列: 使用 dropna 方法可以删…

C++ (MFC) 单程序运行(防止多开程序)

C (MFC) 单程序运行&#xff08;防止多开程序) 项目文件名:MFCAppTest 在 C*****App.cpp 文件中 CMFCAppTestApp::InitInstance 函数中 添加以下代码 //避免程序的多开 xxxx为信号量的名字 可随意CreateMutex(NULL, TRUE, TEXT("MFCAppTest")); if (GetLastError…

oracle—IMU机制

正常的情况下&#xff0c;当事务需要回滚块的时候&#xff0c;是去undo表空间找 现在是在sharepool中分一个IMUbuffer&#xff0c;将所有的回滚信息写入。直接就可以从中取。减少了物理IO 同时这个过程也产生redo&#xff0c;直接就是图中红色的&#xff0c;不防止崩溃 优点 1…

开机自启动android app

Android App开机自启动_android 开机自启动-CSDN博客 注意权限问题&#xff1a; 第二种实现方式&#xff1a;系统桌面应用 问&#xff1a;android的系统桌面应用启动是什么&#xff1a; 答&#xff1a; Android 系统桌面应用是指用户在设备主屏幕上看到的默认启动界面&…

代码随想录算法训练营第四天| 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点面试题 02.07. 链表相交、142.环形链表II

文档讲解&#xff1a;虚拟头节点&#xff0c;三指针&#xff0c;快慢指针&#xff0c;链表相交&#xff0c;环形链表&#xff0c; 技巧&#xff1a; 1、对于指针的操作要画图&#xff0c;明确步骤后好做了 2、使用虚拟头节点可以避免对头节点单独讨论&#xff0c;且方便对头节点…

C++ Primer 6.1 函数基础

函数的形参列表 int func(int v,int v2) {int v,v2;//&#xff01;错误 } 函数返回类型 不能是数组和函数&#xff08;两者都不接受对拷&#xff09;&#xff0c;但可以是指针 局部对象 形参和函数体内部的变量称为局部变量&#xff0c;仅在函数内部可见&#xff0c;隐藏外部…

c++的map的内存布局

以下均基于x86平台64位CentOS或Ubuntu&#xff0c;g8。 有一个指针偶尔会置成0xffffffff&#xff0c;大佬查了几天发现是由于对map的end迭代器进行了错误操作导致的。简化代码如下&#xff1a; struct s_t {std::map<long, int> m;void *p; }; int main() {s_t s;auto …

Python 安卓开发:Kivy、BeeWare、Flet、Flutter

kivy&#xff1a;https://github.com/kivy python-for-android &#xff1a;https://python-for-android.readthedocs.io/en/latest/ BeeWare&#xff1a;https://docs.beeware.org/en/latest/ Flet&#xff1a;https://github.com/flet-dev/flet 把 PySide6 移植到安卓上去&a…