【點云surface】 修剪B樣條曲線擬合

1 介紹

Fitting trimmed B-splines(修剪B樣條曲線擬合)是一種用于對給定的點云數據進行曲線擬合的算法。該算法使用B樣條曲線模型來逼近給定的點云數據,并通過對模型進行修剪來提高擬合的精度和準確性。

B樣條曲線是一種常用的曲線表示方法,它通過一組控制點和節點向量來定義曲線的形狀。B樣條曲線具有局部控制性和平滑性,因此在曲線擬合問題中被廣泛應用。

修剪B樣條曲線擬合算法的基本步驟如下:

  1. 初始化:定義一個B樣條曲線模型,并設置模型的階數、節點向量和控制點。

  2. 迭代優化:通過迭代優化的方法,不斷調整模型的控制點,使得模型更好地逼近給定的點云數據。在每次迭代中,根據給定的擬合參數和優化目標函數,計算出新的控制點位置。

  3. 修剪:根據給定的修剪參數,對擬合的B樣條曲線進行修剪。修剪可以通過刪除不需要的曲線段或調整曲線段的權重來實現。修剪的目的是提高擬合的準確性和精度。

  4. 終止條件:根據設定的終止條件,判斷是否終止迭代優化過程。終止條件可以是達到最大迭代次數、擬合精度滿足要求或其他自定義條件。

  5. 輸出結果:輸出最終的修剪B樣條曲線擬合結果。結果可以是修剪后的B樣條曲線模型,也可以是曲線的控制點和節點向量等表示。

2 效果

3 說明

在進行B樣條曲面擬合時,通常需要先對曲面進行擬合,然后再對曲面上的曲線進行擬合。這是因為曲面上的曲線通常是曲面的邊界或者用于修剪曲面的曲線,它們與曲面的形狀緊密相關,因此需要單獨進行擬合和調整。

首先,進行B樣條曲面擬合時,目標是通過一組控制點和節點向量來逼近給定的點云數據,以生成一個平滑的曲面模型。這個曲面模型可以用來表示曲面的整體形狀。

然后,在曲面擬合的基礎上,進行B樣條曲線擬合。曲線擬合通常是對曲面的邊界曲線或者修剪曲線進行擬合。這些曲線與曲面的形狀緊密相關,因此需要單獨進行擬合和調整。通過對曲線進行擬合,可以更好地捕捉曲面的邊界形狀或者修剪曲線的形狀,從而提高擬合的精度和準確性。

總結起來,進行B樣條曲面擬合后,還需要對曲面上的曲線進行擬合的原因是曲線與曲面的形狀緊密相關,需要單獨進行擬合和調整以提高擬合的精度和準確性。通過分別擬合曲面和曲線,可以更好地捕捉曲面的整體形狀和邊界形狀,從而得到更好的擬合結果。

曲面擬合時的參數

  • order:曲面的階數。該參數定義了B樣條曲面的階數,即每個控制點的影響范圍。較高的階數可以提供更大的自由度,但也會增加計算時間和內存消耗。

  • refinement:細化次數。該參數定義了在擬合過程中進行的細化次數。通過細化,可以在擬合過程中增加新的控制點,以提高擬合的精度和準確性。

  • iterations:迭代次數。該參數定義了擬合過程中的迭代次數。增加迭代次數可以提高擬合的精度,但也會增加計算時間和內存消耗。

  • mesh_resolution:網格分辨率。該參數定義了生成曲面網格的分辨率。較高的分辨率會導致更細致的曲面表示,但也會增加計算時間和內存消耗。

  • params.interior_smoothness:內部平滑度。該參數用于調整曲面內部的平滑度。較大的值會使曲面更平滑。

  • params.interior_weight:內部權重。該參數用于調整曲面內部點對擬合結果的權重。較大的權重會使內部點對擬合結果的影響更大。

  • params.boundary_smoothness:邊界平滑度。該參數用于調整曲面邊界的平滑度。較大的值會使曲面邊界更平滑。

  • params.boundary_weight:邊界權重。該參數用于調整曲面邊界點對擬合結果的權重。較大的權重會使邊界點對擬合結果的影響更大。

曲線擬合的參數

  • curve_params.addCPsAccuracy:添加控制點的精度。控制點是用于定義B樣條曲線形狀的關鍵點。該參數指定了在擬合過程中添加新的控制點的精度。較小的值會導致更精確的擬合結果,但可能會增加計算時間和內存消耗。

  • curve_params.addCPsIteration:添加控制點的迭代次數。在擬合過程中,可以通過迭代的方式不斷添加新的控制點來改進擬合結果。該參數指定了添加控制點的迭代次數。增加迭代次數可以提高擬合的精度,但也會增加計算時間和內存消耗。

  • curve_params.maxCPs:最大控制點數。該參數限制了擬合過程中允許的最大控制點數。超過這個數目的控制點將被丟棄。通過調整這個參數,可以控制擬合結果的復雜度和平滑度。

  • curve_params.accuracy:擬合的精度。該參數指定了擬合結果與原始數據之間的誤差閾值。較小的值會導致更精確的擬合結果,但可能會增加計算時間和內存消耗。

  • curve_params.iterations:迭代次數。該參數指定了擬合過程中的迭代次數。增加迭代次數可以提高擬合的精度,但也會增加計算時間和內存消耗。

  • curve_params.param.closest_point_resolution:最近點的分辨率。該參數用于計算曲線上最近點的分辨率。較小的值會導致更精確的最近點計算,但可能會增加計算時間和內存消耗。

  • curve_params.param.closest_point_weight:最近點的權重。該參數用于計算曲線上最近點的權重。較大的權重會使最近點對擬合結果的影響更大。

  • curve_params.param.closest_point_sigma2:最近點的方差。該參數用于計算曲線上最近點的方差。較小的方差會使最近點對擬合結果的影響更大。

  • curve_params.param.interior_sigma2:內部點的方差。該參數用于計算曲線上內部點的方差。較小的方差會使內部點對擬合結果的影響更大。

  • curve_params.param.smooth_concavity:平滑凹度。該參數用于調整曲線的平滑凹度。較大的值會使曲線更平滑。

  • curve_params.param.smoothness:平滑度。該參數用于調整曲線的平滑度。較大的值會使曲線更平滑。

4 代碼

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/surface/on_nurbs/fitting_surface_tdm.h>
#include <pcl/surface/on_nurbs/fitting_curve_2d_asdm.h>
#include <pcl/surface/on_nurbs/triangulation.h>typedef pcl::PointXYZ Point;
std::ostringstream os;// 將點云數據中的有效點(即非NaN值)提取出來,并以Eigen::Vector3d類型的形式保存起來
void PointCloud2Vector3d(pcl::PointCloud<Point>::Ptr cloud, pcl::on_nurbs::vector_vec3d & data)
{for (unsigned i = 0; i< cloud->size(); i++){Point &p = cloud->at(i);if(!std::isnan(p.x) && !std::isnan(p.z) && !std::isnan(p.z))data.push_back(Eigen::Vector3d(p.x, p.y, p.z));}
}// 將ON_NurbsCurve和ON_NurbsSurface的曲線和控制點可視化顯示在PCLVisualizer中,方便用戶觀察和分析曲線的形狀和控制點的位置。
void visualizeCurve (ON_NurbsCurve &curve,ON_NurbsSurface &surface,pcl::visualization::PCLVisualizer &viewer)
{// 將曲線轉換為點云數據pcl::PointCloud<pcl::PointXYZRGB>::Ptr curve_cloud(new pcl::PointCloud<pcl::PointXYZRGB>);pcl::on_nurbs::Triangulation::convertCurve2PointCloud (curve, surface, curve_cloud, 4);//該函數會將曲線上的點均勻地采樣,并將采樣點作為點云數據的點。// 可視化for(std::size_t i=0; i< curve_cloud->size() - 1; i++){pcl::PointXYZRGB &p1 = curve_cloud->at(i);pcl::PointXYZRGB &p2 = curve_cloud->at(i+1);os << "line" << i;viewer.removeShape(os.str());viewer.addLine<pcl::PointXYZRGB>(p1, p2, 1.0, 0.0, 0.0, os.str());}//pcl::PointCloud<pcl::PointXYZRGB>::Ptr curve_cps (new pcl::PointCloud<pcl::PointXYZRGB>);for(int i=0; i< curve.CVCount(); i++){ON_3dPoint p1;curve.GetCV(i, p1); // 曲線的一個控制點double pnt[3];surface.Evaluate(p1.x ,p1.y, 0, 3, pnt); // 加usn曲面上對應的點的坐標pcl::PointXYZRGB p2;p2.x = float (pnt[0]);p2.y = float (pnt[1]);p2.z = float (pnt[2]);p2.r = 255;p2.g = 0;p2.b = 0;curve_cps->push_back (p2);}viewer.removePointCloud ("cloud_cps");viewer.addPointCloud (curve_cps, "cloud_cps");
}int main()
{pcl::visualization::PCLVisualizer viewer("B-spline surface fitting");viewer.setSize(800, 600);pcl::PCLPointCloud2 cloud2;pcl::PointCloud<Point>::Ptr cloud(new pcl::PointCloud<Point>);if(pcl::io::loadPCDFile("/home/lrj/work/pointCloudData/bun0.pcd", cloud2) == -1)throw std::runtime_error("    PCD file not found.");pcl::fromPCLPointCloud2(cloud2, *cloud);pcl::on_nurbs::NurbsDataSurface data;PointCloud2Vector3d(cloud, data.interior);pcl::visualization::PointCloudColorHandlerCustom<Point> handler(cloud, 0, 255, 0);viewer.addPointCloud<Point>(cloud, handler, "cloud_cylinder");std::printf("     %lu points in data set\n", cloud->size());// ############################################################################// fit B-spline surface/** 整個過程的目的是通過ON-Nurbs算法對給定的點云數據進行曲面擬合,并將擬合結果以三角網格的形式可視化顯示出來。* 通過多次細化和迭代,逐步優化曲面擬合結果,使其更加接近原始點云數據。*/// parametersunsigned order(3); // 曲面的階數unsigned refinement(5); // 細化次數unsigned iterations(10); // 迭代次數unsigned mesh_resolution(256); // 網格分辨率pcl::on_nurbs::FittingSurface::Parameter params;params.interior_smoothness = 0.2; // 內部平滑度params.interior_weight = 1.0; // 內部權重params.boundary_smoothness = 0.2; // 邊界平滑度params.boundary_weight = 0.0; // 邊界權重// 生成初始的曲面擬合結果printf("   surface fitting ...\n");ON_NurbsSurface nurbs = pcl::on_nurbs::FittingSurface::initNurbsPCABoundingBox(order, &data);pcl::on_nurbs::FittingSurface fit(&data, nurbs);//  fit.setQuiet (false); // enable/disable debug output// 將擬合結果轉為三角網格,并將其添加到可視化窗口進行現實pcl::PolygonMesh mesh;pcl::PointCloud<pcl::PointXYZ>::Ptr mesh_cloud(new pcl::PointCloud<pcl::PointXYZ>);std::vector<pcl::Vertices> mesh_vertices;std::string mesh_id = "mesh_nurbs";pcl::on_nurbs::Triangulation::convertSurface2PolygonMesh(fit.m_nurbs, mesh, mesh_resolution);viewer.addPolygonMesh(mesh, mesh_id);// 進行多次曲面細化和求解for (unsigned i=0; i< refinement; i++){fit.refine(0);fit.refine(1);fit.assemble(params);fit.solve();pcl::on_nurbs::Triangulation::convertSurface2Vertices (fit.m_nurbs, mesh_cloud, mesh_vertices, mesh_resolution); // 將曲面轉為頂點數據viewer.updatePolygonMesh<pcl::PointXYZ> (mesh_cloud, mesh_vertices, mesh_id); // 視窗刷新,以便觀察到曲面擬合的過程viewer.spinOnce ();}// 進行一定次數的曲面擬合迭代for (unsigned i = 0; i < iterations; i++){fit.assemble (params);fit.solve ();pcl::on_nurbs::Triangulation::convertSurface2Vertices (fit.m_nurbs, mesh_cloud, mesh_vertices, mesh_resolution);viewer.updatePolygonMesh<pcl::PointXYZ> (mesh_cloud, mesh_vertices, mesh_id);viewer.spinOnce();}// ############################################################################// fit B-spline curve/** 整個曲線擬合的過程的目的是使用ON-Nurbs算法對給定的點云數據進行曲線擬合,并將擬合結果可視化顯示出來。* 通過調整擬合參數,可以控制擬合的精度和平滑度,以得到最優的擬合結果。*/// parameterspcl::on_nurbs::FittingCurve2dAPDM::FitParameter curve_params;curve_params.addCPsAccuracy = 5e-2; // 添加控制點的精度curve_params.addCPsIteration = 3; // 添加控制點的迭代次數curve_params.maxCPs = 200; // 最大控制點數curve_params.accuracy = 1e-3; // 擬合的精度curve_params.iterations = 100; // 迭代次數curve_params.param.closest_point_resolution = 0; // 最近點的分辨率curve_params.param.closest_point_weight = 1.0; // 最近點的權重curve_params.param.closest_point_sigma2 = 0.1; // 最近點的方差curve_params.param.interior_sigma2 = 0.00001; // 內部點的方差curve_params.param.smooth_concavity = 1.0; // 平滑凹度curve_params.param.smoothness = 1.0; // 平滑度// initialisation (circular)printf ("  curve fitting ...\n");pcl::on_nurbs::NurbsDataCurve2d curve_data;curve_data.interior = data.interior_param;curve_data.interior_weight_function.push_back (true);ON_NurbsCurve curve_nurbs = pcl::on_nurbs::FittingCurve2dAPDM::initNurbsCurve2D (order, curve_data.interior);// curve fittingpcl::on_nurbs::FittingCurve2dASDM curve_fit (&curve_data, curve_nurbs);// curve_fit.setQuiet (false); // enable/disable debug outputcurve_fit.fitting (curve_params);visualizeCurve (curve_fit.m_nurbs, fit.m_nurbs, viewer);// ############################################################################// triangulation of trimmed surfaceprintf ("  triangulate trimmed surface ...\n");viewer.removePolygonMesh (mesh_id);pcl::on_nurbs::Triangulation::convertTrimmedSurface2PolygonMesh (fit.m_nurbs, curve_fit.m_nurbs, mesh,mesh_resolution); // 將擬合的曲面、曲線轉為三角網格viewer.addPolygonMesh (mesh, mesh_id);// save trimmed B-spline surfaceif ( fit.m_nurbs.IsValid() ){ONX_Model model;ONX_Model_Object& surf = model.m_object_table.AppendNew();surf.m_object = new ON_NurbsSurface(fit.m_nurbs);surf.m_bDeleteObject = true;surf.m_attributes.m_layer_index = 1;surf.m_attributes.m_name = "surface";ONX_Model_Object& curv = model.m_object_table.AppendNew();curv.m_object = new ON_NurbsCurve(curve_fit.m_nurbs);curv.m_bDeleteObject = true;curv.m_attributes.m_layer_index = 2;curv.m_attributes.m_name = "trimming curve";//        model.Write(file_3dm.c_str());
//        printf("  model saved: %s\n", file_3dm.c_str());}printf ("  ... done.\n");viewer.spin();return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/167963.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/167963.shtml
英文地址,請注明出處:http://en.pswp.cn/news/167963.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【element優化經驗】el-dialog修改title樣式

目錄 前言 解決之路 1.把默認的這個圖標隱藏&#xff0c;官方的api有這個屬性&#xff1a;showClose值設置false. 2.title插槽定制&#xff1a;左邊定制標題&#xff0c;右邊定制按鈕區域。 3.背景顏色修改&#xff1a;默認title是有padding的需要把它重寫調&#xff0c;然…

基于卷積神經網絡CNN開發構建HAR人類行為識別Human Activity Recognition【完整代碼實踐】

行為識別相關的開發實踐在我們之前的博文中也有過相關的實踐了,感興趣的話可以自行移步閱讀即可:《python實現基于TNDADATASET的人體行為識別》 《UCI行為識別——Activity recognition with healthy older people using a batteryless wearable sensor Data Set》《人體行為…

基于 STM32Cube.AI 的嵌入式人臉識別算法實現

本文介紹了如何使用 STM32Cube.AI 工具開發嵌入式人臉識別算法。首先&#xff0c;我們將簡要介紹 STM32Cube.AI 工具和 STM32F系列單片機的特點。接下來&#xff0c;我們將詳細討論如何使用 STM32Cube.AI 工具鏈和相關庫來進行人臉識別算法的開發和優化。最后&#xff0c;我們提…

Netty實現websocket且實現url傳參的兩種方式(源碼分析)

1、先構建基本的netty框架 再下面的代碼中我構建了一個最基本的netty實現websocket的框架&#xff0c;其他個性化部分再自行添加。 Slf4j public class TeacherServer {public void teacherStart(int port) throws InterruptedException {NioEventLoopGroup boss new NioEve…

Day40力扣打卡

打卡記錄 包子湊數&#xff08;裴蜀定理 DP&#xff09; 根據裴蜀定理&#xff0c;存在 c gcd(a, b) 使不定方程ax by c滿足條件&#xff0c;如果gcd(a, b) 1即a與b互素的情況下&#xff0c;就會 ax by 1&#xff0c;由于為1可以構造后面的無窮數字&#xff0c;故得到結…

Centos7 離線安裝 CDH7.1.7

1. 安裝CDH的準備工作&#xff08;所有節點都要執行&#xff09; 1.1 準備環境 角色 IP k8s-master 192.168.181.129 k8s-node1 192.168.181.130 k8s-node2 192.168.181.131 1.2 安裝JDK # https://www.oracle.com/java/technologies/downloads/#java11 wget rpm -ivh…

亞馬遜Listing怎么寫!親身經驗分享

亞馬遜運營的重要環節之一&#xff0c;listing的攥寫&#xff0c;可以決定了產品的搜索排名&#xff0c;用戶的點擊率和轉化率&#xff0c;那么如果你的產品排名或者轉化不理想的情況&#xff0c;可以考慮對listing進行優化&#xff0c;在關鍵詞過多和語句流程通順的情況下&…

js獲取時間日期

目錄 Date 對象 1. 獲取當前時間 2. 獲取特定日期時間 Date 對象的方法 1. 獲取各種日期時間組件 2. 獲取星期幾 3. 獲取時間戳 格式化日期時間 1. 使用 toLocaleString() 方法 2. 使用第三方庫 UNIX 時間戳 內部表示 時區 Date 對象 JavaScript中內置的 Date 對象…

數據挖掘之PCA-主成分分析

PCA的用處&#xff1a;找出反應數據中最大變差的投影&#xff08;就是拉的最開&#xff09;。 在減少需要分析的指標同時&#xff0c;盡量減少原指標包含信息的損失&#xff0c;以達到對所收集數據進行全面分析的目的 但是什么時候信息保留的最多呢&#xff1f;具體一點&#…

?飛凌嵌入式FCU2601網關,為工商業儲能EMS注入智慧的力量

一、火熱的儲能行業&#xff0c;尋求新的市場機會 最近一段時間以來&#xff0c;世界儲能大會、上海儲能展、能源電子產業發展大會等多個儲能相關論壇和展覽密集登場&#xff0c;即使“內卷”已成為了業內討論的熱詞&#xff0c;但尋求新的市場機會仍然是行業共識&#xff0c;…

常用Redis的鍵命令參考

一、DEL DEL key [key …] 刪除給定的一個或多個 key 。 不存在的 key 會被忽略。 #刪除單個鍵127.0.0.1:6379> set name zhangsan OK 127.0.0.1:6379> del name (integer) 1# 刪除一個不存在的 key&#xff0c; 失敗&#xff0c;沒有 key 被刪除127.0.0.1:6379> E…

Qt C++中調用python,并將軟件打包發布,python含第三方依賴

工作中遇到qt c調用我的python 代碼&#xff0c;并且想要一鍵打包&#xff0c;這里我根據參考的以及個人實踐的結果來簡單實現一下。 環境&#xff1a;windows系統&#xff0c;QT Creater 4.5&#xff0c; python 3.8&#xff08;anaconda虛擬環境&#xff09; 1. 簡單QT調用…

【 Kubernetes 風云錄 】- Istio 應用多版本流量控制

文章目錄 原理實現DeploymentVirtualServiceDestinationRule 約束部署 目的: 根據不同的引擎版本&#xff0c;可以把請求發送到指定的引擎上。可以實現版本降級。 原理 Istio通過VirtualService和DestinationRule兩個資源對象來實現流量管理&#xff0c;其中VirtualService用于…

LeetCode Hot100 98.驗證二叉搜索樹

題目&#xff1a; 給你一個二叉樹的根節點 root &#xff0c;判斷其是否是一個有效的二叉搜索樹。 有效 二叉搜索樹定義如下&#xff1a; 節點的左子樹只包含 小于 當前節點的數。節點的右子樹只包含 大于 當前節點的數。所有左子樹和右子樹自身必須也是二叉搜索樹。 方法一…

electron windows robotjs 安裝教程

Robotjs 安裝 前言第一步 : 安裝python第二步 : 安裝Visual Studio 2022第三步 : 安裝robotjs 前言 robotjs可以控制鼠標鍵盤&#xff0c;獲取屏幕內容&#xff0c;配合electron可做很多自動化操作。windows下配置環境有很多坑&#xff0c;很多文章都太舊了。試了很多次發現了…

ky10 server x86 auditd安裝(日志審計系統)

概述 Auditd工具可以幫助運維人員審計Linux&#xff0c;分析發生在系統中的發生的事情。Linux 內核有用日志記錄事件的能力&#xff0c;包括記錄系統調用和文件訪問。管理員可以檢查這些日志&#xff0c;確定是否存在安全漏洞&#xff08;如多次失敗的登錄嘗試&#xff0c;或者…

golang學習筆記——接口和繼承比較2

接口和繼承 現在有一個需要要求大學生和足球運動員掌握英語技能&#xff0c;請問怎么實現? 給運動員和學生結構體添加studyEnglish方法顯示是可以的&#xff0c;但是籃球動員和中學生也學習了英語&#xff0c;顯示不行。這時&#xff0c;我們可以直接給足球運動員和大學生添加…

跳轉應用市場詳情頁market

關于作者&#xff1a;CSDN內容合伙人、技術專家&#xff0c; 從零開始做日活千萬級APP。 專注于分享各領域原創系列文章 &#xff0c;擅長java后端、移動開發、商業變現、人工智能等&#xff0c;希望大家多多支持。 未經允許不得轉載 目錄 一、導讀二、概覽三、跳轉到各大廠商應…

播放器開發(四):多線程解復用與解碼模塊實現

學習課題&#xff1a;逐步構建開發播放器【QT5 FFmpeg6 SDL2】 前言 根據第一章內容&#xff0c;我們首先可以先把解復用和解碼模塊完成&#xff0c;其中需要使用到多線程以及隊列&#xff0c;還需要使用FFmpeg進行解復用和解碼動作的實現。 創建BaseQueue基類 BaseQueue.h…

亞馬遜兩步驗證有哪些驗證方法?

亞馬遜通常提供多種兩步驗證的方式&#xff0c;包括短信&#xff08;通過手機接收驗證碼&#xff09;和認證器應用程序&#xff08;如Google Authenticator、Authy等&#xff09;。選擇你偏好的方式。 短信驗證&#xff1a; 如果選擇短信驗證&#xff0c;需要將你的手機號碼關聯…