使用 PCL 和 Qt 實現點云可視化與交互

下面我將介紹如何結合點云庫(PCL)和Qt框架(特別是QML)來實現點云的可視化與交互功能,包括高亮選擇等效果。

1. 基本架構設計

首先需要建立一個結合PCL和Qt的基本架構:

// PCLQtViewer.h
#pragma once#include <QObject>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>class PCLQtViewer : public QObject
{Q_OBJECTpublic:explicit PCLQtViewer(QObject* parent = nullptr);// 加載點云Q_INVOKABLE void loadPointCloud(const QString& filePath);// 獲取點云數據供QML使用Q_INVOKABLE QVariantList getPointCloudData() const;// 高亮選擇的點Q_INVOKABLE void highlightPoints(const QVariantList& indices);signals:void pointCloudLoaded();void selectionChanged();private:pcl::PointCloud<pcl::PointXYZRGB>::Ptr m_cloud;std::vector<int> m_selectedIndices;
};

2. PCL與Qt的集成實現

// PCLQtViewer.cpp
#include "PCLQtViewer.h"
#include <pcl/io/pcd_io.h>
#include <pcl/common/colors.h>PCLQtViewer::PCLQtViewer(QObject* parent) : QObject(parent), m_cloud(new pcl::PointCloud<pcl::PointXYZRGB>())
{
}void PCLQtViewer::loadPointCloud(const QString& filePath)
{if (pcl::io::loadPCDFile<pcl::PointXYZRGB>(filePath.toStdString(), *m_cloud) == -1) {qWarning() << "Failed to load PCD file";return;}emit pointCloudLoaded();
}QVariantList PCLQtViewer::getPointCloudData() const
{QVariantList points;for (const auto& point : *m_cloud) {QVariantMap pt;pt["x"] = point.x;pt["y"] = point.y;pt["z"] = point.z;pt["r"] = point.r;pt["g"] = point.g;pt["b"] = point.b;pt["selected"] = std::find(m_selectedIndices.begin(), m_selectedIndices.end(), &point - &m_cloud->points[0]) != m_selectedIndices.end();points.append(pt);}return points;
}void PCLQtViewer::highlightPoints(const QVariantList& indices)
{m_selectedIndices.clear();for (const auto& idx : indices) {m_selectedIndices.push_back(idx.toInt());}emit selectionChanged();
}

3. QML點云可視化界面

qml

// main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import Qt3D.Core 2.15
import Qt3D.Render 2.15
import Qt3D.Input 2.15
import Qt3D.Extras 2.15ApplicationWindow {id: windowwidth: 1280height: 720visible: truePCLQtViewer {id: pclVieweronPointCloudLoaded: pointCloudModel.reload()onSelectionChanged: pointCloudModel.reload()}// 3D視圖Qt3DWindow {id: view3danchors.fill: parentCamera {id: cameraprojectionType: CameraLens.PerspectiveProjectionfieldOfView: 45aspectRatio: view3d.width / view3d.heightnearPlane: 0.1farPlane: 1000.0position: Qt.vector3d(0.0, 0.0, 10.0)upVector: Qt.vector3d(0.0, 1.0, 0.0)viewCenter: Qt.vector3d(0.0, 0.0, 0.0)}// 點云實體Entity {id: pointCloudEntitycomponents: [Transform {id: cloudTransformscale: 1.0},GeometryRenderer {id: pointGeometryprimitiveType: GeometryRenderer.Pointsgeometry: Geometry {boundingVolumePositionAttribute: positionAttribute {id: positionattributeType: Attribute.VertexAttributevertexBaseType: Attribute.FloatvertexSize: 3byteOffset: 0byteStride: 6 * 4count: pointCloudModel.countbuffer: pointBuffer}Attribute {id: colorattributeType: Attribute.ColorAttributevertexBaseType: Attribute.FloatvertexSize: 3byteOffset: 3 * 4byteStride: 6 * 4count: pointCloudModel.countbuffer: pointBuffer}Buffer {id: pointBufferdata: pointCloudModel.geometryData}}},Material {effect: Effect {techniques: Technique {renderPasses: RenderPass {shaderProgram: ShaderProgram {vertexShaderCode: "#version 330in vec3 vertexPosition;in vec3 vertexColor;out vec3 color;uniform mat4 mvp;void main() {color = vertexColor;gl_Position = mvp * vec4(vertexPosition, 1.0);gl_PointSize = 3.0;}"fragmentShaderCode: "#version 330in vec3 color;out vec4 fragColor;void main() {fragColor = vec4(color, 1.0);}"}}}}}]}OrbitCameraController {camera: camera}}// 點云數據模型ListModel {id: pointCloudModelfunction reload() {clear();var points = pclViewer.getPointCloudData();for (var i = 0; i < points.length; i++) {append(points[i]);}}property var geometryData: {var data = new Float32Array(count * 6);for (var i = 0; i < count; i++) {var pt = get(i);data[i * 6] = pt.x;data[i * 6 + 1] = pt.y;data[i * 6 + 2] = pt.z;// 選中的點顯示為紅色,否則使用原始顏色if (pt.selected) {data[i * 6 + 3] = 1.0;data[i * 6 + 4] = 0.0;data[i * 6 + 5] = 0.0;} else {data[i * 6 + 3] = pt.r / 255.0;data[i * 6 + 4] = pt.g / 255.0;data[i * 6 + 5] = pt.b / 255.0;}}return data;}}// 控制面板Rectangle {width: 300height: parent.heightcolor: "#eee"Column {spacing: 10padding: 10Button {text: "加載點云"onClicked: fileDialog.open()}ListView {id: selectionListViewwidth: parent.widthheight: 200model: ListModel {}delegate: ItemDelegate {width: parent.widthtext: "點 " + indexhighlighted: pointCloudModel.get(index).selectedonClicked: {pclViewer.highlightPoints([index]);}}}}}FileDialog {id: fileDialogtitle: "選擇點云文件"folder: shortcuts.homenameFilters: ["PCD文件 (*.pcd)"]onAccepted: pclViewer.loadPointCloud(fileDialog.fileUrl)}
}

4. 主程序集成

cpp

// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "PCLQtViewer.h"int main(int argc, char *argv[])
{QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QGuiApplication app(argc, argv);qmlRegisterType<PCLQtViewer>("PCL", 1, 0, "PCLQtViewer");QQmlApplicationEngine engine;engine.load(QUrl(QStringLiteral("qrc:/main.qml")));if (engine.rootObjects().isEmpty())return -1;return app.exec();
}

5. 高級功能擴展

點云聚類高亮

cpp

// 在PCLQtViewer類中添加
Q_INVOKABLE void highlightCluster(int clusterId)
{// 假設已經執行過聚類算法,結果存儲在m_clusterIndices中m_selectedIndices = m_clusterIndices[clusterId];emit selectionChanged();
}

3D框選功能

qml

// 在Qt3DWindow中添加
Entity {components: [ObjectPicker {id: pickerdragEnabled: trueonClicked: {var worldPos = pick.worldPosition;// 轉換坐標并選擇附近的點pclViewer.selectPointsInSphere(worldPos.x, worldPos.y, worldPos.z, 0.5);}onPressed: {// 開始框選selectionRect.visible = true;selectionRect.x = pick.x;selectionRect.y = pick.y;}onReleased: {// 結束框選selectionRect.visible = false;var selected = selectPointsInRectangle(selectionRect);pclViewer.highlightPoints(selected);}}]
}Rectangle {id: selectionRectvisible: falsecolor: "#8033B5E5"border.color: "#0033B5E5"
}

點云著色模式切換

qml

ComboBox {model: ["原始顏色", "高度著色", "曲率著色", "聚類著色"]onCurrentIndexChanged: pclViewer.setColorMode(currentIndex)
}

6. 性能優化建議

  1. 點云分塊加載:對于大型點云,實現分塊加載機制

  2. LOD(細節層次):根據視點距離動態調整顯示細節

  3. 后臺處理:將PCL處理任務放在后臺線程

  4. GPU加速:使用計算著色器處理點云數據

  5. 空間索引:使用八叉樹等結構加速空間查詢

7. 項目配置(CMake)

cmake_minimum_required(VERSION 3.5)project(PCL_Qt_Viewer)find_package(Qt5 COMPONENTS Quick QuickControls2 3DCore 3DRender 3DInput 3DExtras REQUIRED)
find_package(PCL 1.8 REQUIRED)set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD 14)add_executable(${PROJECT_NAME}main.cppPCLQtViewer.cppPCLQtViewer.h
)target_link_libraries(${PROJECT_NAME}Qt5::QuickQt5::QuickControls2Qt5::3DCoreQt5::3DRenderQt5::3DInputQt5::3DExtras${PCL_LIBRARIES}
)

這種集成方式充分利用了PCL強大的點云處理能力和Qt/QML出色的UI/交互能力,可以構建出功能豐富、交互友好的點云處理應用程序。

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

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

相關文章

mybatis plus打印sql日志到指定目錄

1、mybatis plus打印sql日志 參考文檔&#xff1a;mybatis plus打印sql日志_mybatisplus日志打印-CSDN博客 2、修改 修改InfoLevelLogger Override public void debug(String s) {// 修改這里logger.info(s);log.debug(s); } 增加&#xff1a;log.debug(s); 修改logback.x…

vue3 watch和watchEffect 的用法和區別

在 Vue 3 里&#xff0c;watch 和 watchEffect 都是用于響應式數據變化的 API&#xff0c;但它們在使用方法和應用場景上存在差異。下面詳細介紹它們的用法和區別。 用法 watch watch 用于監聽特定的響應式數據源&#xff0c;當數據源發生變化時&#xff0c;會執行相應的回調…

Qt中修改了UI設計文件后編譯不生效問題的解決辦法

復制工程過來后&#xff1a; 1、刪除build文件 2、刪除.user文件&#xff0c;恢復為文件最初的那樣 3、執行make distclean,刪除所有由先前構建過程生成的文件 4、再次打開工程&#xff0c;修改ui文件編譯生效&#xff01;

EtherCAT轉ProfiNet邊緣計算網關配置優化:汽車制造場景下PLC與機器人協同作業案例

1.行業背景與需求分析 智能汽車焊裝車間是汽車制造的核心工藝環節&#xff0c;某德國豪華品牌在其上海MEB工廠新建的焊裝車間中&#xff0c;采用西門子S7-1500PLC作為ProfiNet主站&#xff0c;負責整線協調與質量追溯&#xff1b;同時部署KUKAKR1500Titan機器人&#xff08;Eth…

day46—雙指針-兩數之和-輸入有序數組(LeetCode-167)

題目描述 給你一個下標從 1 開始的整數數組 numbers &#xff0c;該數組已按 非遞減順序排列 &#xff0c;請你從數組中找出滿足相加之和等于目標數 target 的兩個數。如果設這兩個數分別是 numbers[index1] 和 numbers[index2] &#xff0c;則 1 < index1 < index2 &l…

線性代數 | 知識點整理 Ref 1

注&#xff1a;本文為 “線性代數 | 知識點整理” 相關文章合輯。 因 csdn 篇幅合并超限分篇連載&#xff0c;本篇為 Ref 1。 略作重排&#xff0c;未整理去重。 圖片清晰度限于引文原狀。 如有內容異常&#xff0c;請看原文。 線性代數知識匯總 Arrow 于 2016-11-27 16:27:5…

比特幣的跨輸入簽名聚合(Cross-Input Signature Aggregation,CISA)

1. 引言 2024 年&#xff0c;人權基金會&#xff08;Human Rights Foundation&#xff0c;簡稱 HRF&#xff09;啟動了一項研究獎學金計劃&#xff0c;旨在探討“跨輸入簽名聚合”&#xff08;Cross-Input Signature Aggregation&#xff0c;簡稱 CISA&#xff09;的潛在影響。…

3.基礎開發工具

1.軟件包管理器 1.1什么是軟件包 ? 在Linux下安裝軟件, ?個通常的辦法是下載到程序的源代碼, 并進?編譯, 得到可執?程序. ? 但是這樣太?煩了, 于是有些?把?些常?的軟件提前編譯好, 做成軟件包(可以理解成windows上 的安裝程序)放在?個服務器上, 通過包管理器可以很…

Golang errors 包快速上手

文章目錄 1.變量2.類型3.函數3.1 New3.2 Is簡介函數簽名核心功能示例代碼使用場景注意事項小結 3.3 As簡介函數簽名核心功能示例代碼使用場景注意事項小結 3.4 Unwrap簡介函數簽名核心功能使用示例使用場景注意事項小結 3.5 Join簡介函數簽名核心功能使用場景注意事項小結 4.小…

Java File 類詳解

Java File 類詳解 File 類是 Java 中用于表示文件和目錄路徑名的抽象類&#xff0c;位于 java.io 包中。它提供了豐富的 API&#xff0c;用于操作文件系統&#xff0c;包括創建、刪除、重命名、查詢文件屬性等功能。 1. File 類核心知識點 &#xff08;1&#xff09;構造方法…

基于javaweb的SpringBoot兒童愛心管理系統設計與實現(源碼+文檔+部署講解)

技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、小程序、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;免費功能設計、開題報告、任務書、中期檢查PPT、系統功能實現、代碼編寫、論文編寫和輔導、論文…

Unity Nav Mesh導航系統的簡單使用

標題 1.下載。2.面板位置3.object面板4.Area面板5.Bake面板6.Agent面板7.Nav Mesh Agent組件8.Nav Mesh Obstacle組件9.簡單使用 1.下載。 unity2022以上版本要去packageManager中下載。 2.面板位置 3.object面板 Navigation Static&#xff1a;設置該物體是否被列入靜態尋路…

FairyGUI圖標文字合批失敗的原因

1&#xff09;FairyGUI圖標文字合批失敗的原因 2&#xff09;為什么Cubemap的內存占用超高 3&#xff09;如何找到網格某個切面的中心點 4&#xff09;為什么SafeZone在倒屏后方向相反 這是第428篇UWA技術知識分享的推送&#xff0c;精選了UWA社區的熱門話題&#xff0c;涵蓋了…

[BUG]Cursor C++擴展不支持

本文內容組織形式 問題描述失效原因解決方案使用野版C Extension 猜你喜歡結語 問題描述 日期&#xff1a;20250419 操作系統&#xff1a; mac C代碼沒有辦法進行跳轉&#xff0c;并且和以前的文本標亮也不同 并且還有如下問題彈窗 C/C 擴展只能與 Microsoft Visual Studio…

深?理解 JVM 執?引擎

深?理解 JVM 執?引擎 其中前端編譯是在 JVM 虛擬機之外執?&#xff0c;所以與 JVM 虛擬機沒有太?的關系。任何編程語?&#xff0c;只要能夠編譯出 滿? JVM 規范的 Class ?件&#xff0c;就可以提交到 JVM 虛擬機執?。?于編譯的過程&#xff0c;如果你不是想要專?去研…

Ubuntu 部署 DeepSeek

在 Ubuntu 系統上部署 DeepSeek 模型&#xff0c;能讓用戶利用其強大的人工智能能力&#xff0c;同時保障數據的安全性與操作的自主性。不過&#xff0c;這一過程涉及諸多技術細節&#xff0c;需要謹慎操作。以下將為你詳細介紹在 Ubuntu 系統部署 DeepSeek 的操作步驟及注意事…

通義靈碼 Rules 庫合集來了,覆蓋Java、TypeScript、Python、Go、JavaScript 等

通義靈碼新上的外掛 Project Rules 獲得了開發者的一致好評&#xff1a;最小成本適配我的開發風格、相當把團隊經驗沉淀下來&#xff0c;是個很好功能…… 那么有哪些現成的 Rules 可以抄作業呢&#xff0c;今天我們官方輸出了 Java、TypeScript、Python、Go、JavaScript 等語…

山東大學軟件學院項目實訓-基于大模型的模擬面試系統-Token過期重定向問題

項目結構 ├── assets/ # 靜態資源&#xff08;CSS/圖片&#xff09; ├── components/ # Vue 組件 ├── layouts/ # 布局模板 ├── pages/ # 自動生成路由 ├── plugins/ # 插件&#xff08;如 axios 攔截器&#xff09; …

SAP案例:珠海漢勝科技SAP S/4 HANA智能制造實踐與價值實現

客戶簡介 珠海漢勝科技股份有限公司為高科技生產企業&#xff0c;成立于1985年&#xff0c;擁有員工近2000人。主要從事生產、銷售、研發&#xff1a;光纖光纜、電線、電纜及附件、鋁塑復合管&#xff1b;光纖光纜、電纜、電線生產項目的策劃及技術咨詢。它致力于為國內外無線電…

Spring Boot 項目中發布流式接口支持實時數據向客戶端推送

1、pom依賴添加 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency>2、事例代碼 package com.pojo.prj.controller;import com.pojo.common.core.utils.String…