Intel® RealSense™ SDK:Python GUI开发实战指南

Intel® RealSense™ SDK:Python GUI开发实战指南

【免费下载链接】librealsense Intel® RealSense™ SDK 【免费下载链接】librealsense 项目地址: https://gitcode.com/GitHub_Trending/li/librealsense

引言:告别命令行,构建交互式深度视觉应用

你是否还在为RealSense相机的原始数据流发愁?是否希望用直观的界面展示深度图像与点云数据?本文将带你从零开始,掌握基于Python的RealSense GUI应用开发,通过5个实战案例和3种主流GUI框架对比,打造专业级深度视觉交互系统。读完本文,你将获得:

  • 3套完整的GUI开发模板(OpenCV/PyQt/Pyglet)
  • 深度数据可视化的4种核心技术
  • 多相机同步与点云交互的实现方案
  • 性能优化与跨平台部署的关键技巧

环境准备:搭建高效开发框架

开发环境配置

组件推荐版本安装命令国内加速方案
Python3.9-3.12sudo apt install python3 python3-pip清华源 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
RealSense SDK2.55.1+pip install pyrealsense2国内镜像
OpenCV4.5.5+pip install opencv-python同上
PyQt55.15.6pip install pyqt5同上
Pyglet1.5.27pip install pyglet同上

源码编译指南(高级用户)

# 克隆仓库
git clone https://gitcode.com/GitHub_Trending/li/librealsense.git
cd librealsense

# 编译Python绑定
mkdir build && cd build
cmake ../ -DBUILD_PYTHON_BINDINGS=ON -DPYTHON_EXECUTABLE=$(which python3)
make -j4
sudo make install

# 配置环境变量
echo 'export PYTHONPATH=$PYTHONPATH:/usr/local/lib' >> ~/.bashrc
source ~/.bashrc

基础篇:OpenCV快速可视化方案

核心原理与架构

mermaid

实时深度彩色双窗口查看器

import pyrealsense2 as rs
import numpy as np
import cv2

class RealSenseViewer:
    def __init__(self):
        # 配置数据流
        self.pipeline = rs.pipeline()
        config = rs.config()
        
        # 获取设备信息并配置分辨率
        pipeline_wrapper = rs.pipeline_wrapper(self.pipeline)
        pipeline_profile = config.resolve(pipeline_wrapper)
        device = pipeline_profile.get_device()
        
        # 启用深度和彩色流
        config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
        config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
        
        # 启动流
        self.profile = self.pipeline.start(config)
        
        # 创建对齐对象(深度对齐到彩色)
        align_to = rs.stream.color
        self.align = rs.align(align_to)
        
        # 创建窗口
        cv2.namedWindow('RealSense Depth', cv2.WINDOW_AUTOSIZE)
        cv2.namedWindow('RealSense Color', cv2.WINDOW_AUTOSIZE)
        
        # 添加滑动条控制深度颜色映射
        cv2.createTrackbar('Color Map', 'RealSense Depth', 0, 11, self.on_trackbar)
        self.color_map = 0

    def on_trackbar(self, val):
        self.color_map = val

    def run(self):
        try:
            while True:
                # 等待帧
                frames = self.pipeline.wait_for_frames()
                
                # 对齐深度到彩色流
                aligned_frames = self.align.process(frames)
                aligned_depth_frame = aligned_frames.get_depth_frame()
                color_frame = aligned_frames.get_color_frame()
                
                if not aligned_depth_frame or not color_frame:
                    continue
                
                # 转换为numpy数组
                depth_image = np.asanyarray(aligned_depth_frame.get_data())
                color_image = np.asanyarray(color_frame.get_data())
                
                # 应用颜色映射
                depth_colormap = cv2.applyColorMap(
                    cv2.convertScaleAbs(depth_image, alpha=0.03), 
                    self.color_map
                )
                
                # 显示图像
                cv2.imshow('RealSense Depth', depth_colormap)
                cv2.imshow('RealSense Color', color_image)
                
                # 处理按键事件
                key = cv2.waitKey(1)
                if key & 0xFF == ord('q') or key == 27:
                    cv2.destroyAllWindows()
                    break
                elif key == ord('s'):
                    # 保存当前帧
                    cv2.imwrite('depth.png', depth_colormap)
                    cv2.imwrite('color.png', color_image)
                    print("图像已保存")

        finally:
            # 停止流
            self.pipeline.stop()

if __name__ == "__main__":
    viewer = RealSenseViewer()
    viewer.run()

关键技术点解析

  1. 帧同步机制:使用rs.align实现深度与彩色图像的空间对齐,确保像素级匹配
  2. 颜色映射优化:通过滑动条动态切换12种OpenCV颜色映射(如JET、RAINBOW)
  3. 事件处理系统:实现图像保存、退出等基本交互功能
  4. 性能优化:通过convertScaleAbs调整深度数据可视化范围,增强细节表现力

进阶篇:PyQt5交互式应用开发

模块化架构设计

mermaid

核心功能实现

import sys
import numpy as np
import pyrealsense2 as rs
from PyQt5.QtWidgets import (QApplication, QMainWindow, QTabWidget, QWidget, 
                            QVBoxLayout, QHBoxLayout, QPushButton, QLabel, 
                            QSlider, QComboBox)
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt, QThread, pyqtSignal

class StreamThread(QThread):
    frame_ready = pyqtSignal(np.ndarray, np.ndarray)
    
    def __init__(self, pipeline):
        super().__init__()
        self.pipeline = pipeline
        self.running = True
        self.align = rs.align(rs.stream.color)
        
    def run(self):
        while self.running:
            frames = self.pipeline.wait_for_frames()
            aligned_frames = self.align.process(frames)
            
            depth_frame = aligned_frames.get_depth_frame()
            color_frame = aligned_frames.get_color_frame()
            
            if not depth_frame or not color_frame:
                continue
                
            depth_image = np.asanyarray(depth_frame.get_data())
            color_image = np.asanyarray(color_frame.get_data())
            
            self.frame_ready.emit(depth_image, color_image)
            
    def stop(self):
        self.running = False
        self.wait()

class RealSenseQtApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("RealSense PyQt可视化工具")
        self.setGeometry(100, 100, 1280, 720)
        
        # 初始化相机
        self.pipeline = rs.pipeline()
        config = rs.config()
        config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
        config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
        
        # 启动相机
        self.pipeline.start(config)
        
        # 创建UI
        self.setup_ui()
        
        # 启动流线程
        self.stream_thread = StreamThread(self.pipeline)
        self.stream_thread.frame_ready.connect(self.update_frames)
        self.stream_thread.start()
        
    def setup_ui(self):
        # 创建中心部件
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        main_layout = QVBoxLayout(self.central_widget)
        
        # 创建标签页
        self.tabs = QTabWidget()
        main_layout.addWidget(self.tabs)
        
        # 图像显示标签页
        self.image_tab = QWidget()
        self.tabs.addTab(self.image_tab, "图像视图")
        
        # 图像布局
        image_layout = QHBoxLayout(self.image_tab)
        
        # 深度图像显示
        self.depth_label = QLabel("深度图像")
        self.depth_label.setAlignment(Qt.AlignCenter)
        image_layout.addWidget(self.depth_label)
        
        # 彩色图像显示
        self.color_label = QLabel("彩色图像")
        self.color_label.setAlignment(Qt.AlignCenter)
        image_layout.addWidget(self.color_label)
        
        # 控制面板
        control_layout = QHBoxLayout()
        
        # 颜色映射选择
        self.color_map_combo = QComboBox()
        self.color_map_combo.addItems([
            "JET", "RAINBOW", "OCEAN", "WINTER", "SPRING", 
            "SUMMER", "AUTUMN", "BONE", "COOL", "HOT", "PINK", "HSV"
        ])
        control_layout.addWidget(QLabel("颜色映射:"))
        control_layout.addWidget(self.color_map_combo)
        
        # 深度范围控制
        self.depth_scale_slider = QSlider(Qt.Horizontal)
        self.depth_scale_slider.setRange(1, 100)
        self.depth_scale_slider.setValue(3)
        control_layout.addWidget(QLabel("深度缩放:"))
        control_layout.addWidget(self.depth_scale_slider)
        
        # 保存按钮
        self.save_btn = QPushButton("保存图像")
        self.save_btn.clicked.connect(self.save_images)
        control_layout.addWidget(self.save_btn)
        
        main_layout.addLayout(control_layout)
        
    def update_frames(self, depth_image, color_image):
        # 应用颜色映射
        color_map = self.color_map_combo.currentIndex()
        alpha = self.depth_scale_slider.value() / 100.0
        
        depth_colormap = cv2.applyColorMap(
            cv2.convertScaleAbs(depth_image, alpha=alpha), 
            color_map
        )
        
        # 转换为Qt图像格式
        depth_qimg = QImage(
            depth_colormap.data, depth_colormap.shape[1], depth_colormap.shape[0],
            depth_colormap.strides[0], QImage.Format_RGB888
        )
        
        color_qimg = QImage(
            color_image.data, color_image.shape[1], color_image.shape[0],
            color_image.strides[0], QImage.Format_BGR888
        )
        
        # 更新标签
        self.depth_label.setPixmap(QPixmap.fromImage(depth_qimg).scaled(
            self.depth_label.width(), self.depth_label.height(), Qt.KeepAspectRatio
        ))
        
        self.color_label.setPixmap(QPixmap.fromImage(color_qimg).scaled(
            self.color_label.width(), self.color_label.height(), Qt.KeepAspectRatio
        ))
        
    def save_images(self):
        # 实现图像保存功能
        pass
        
    def closeEvent(self, event):
        # 停止线程和相机
        self.stream_thread.stop()
        self.pipeline.stop()
        event.accept()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = RealSenseQtApp()
    window.show()
    sys.exit(app.exec_())

PyQt5方案优势

  1. 丰富的UI组件:提供按钮、滑动条、标签页等原生控件,构建专业界面
  2. 强大的信号槽机制:实现非阻塞式数据更新,避免界面卡顿
  3. 跨平台一致性:在Windows、Linux和macOS上保持一致的外观和行为
  4. 可扩展性强:易于集成菜单、工具栏、状态栏等复杂组件

高级篇:3D点云可视化与交互

Pyglet 3D点云查看器

import math
import numpy as np
import pyglet
import pyglet.gl as gl
import pyrealsense2 as rs

class PointCloudViewer:
    def __init__(self):
        # 窗口设置
        self.width, self.height = 1280, 720
        self.window = pyglet.window.Window(
            width=self.width, height=self.height, 
            caption='RealSense 3D点云查看器',
            resizable=True
        )
        
        # 相机参数
        self.pitch, self.yaw = 0, 0
        self.distance = 2.0
        self.translation = np.array([0, 0, 0], dtype=np.float32)
        
        # 点云数据
        self.vertices = None
        self.colors = None
        
        # 配置RealSense
        self.pipeline = rs.pipeline()
        config = rs.config()
        config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
        config.enable_stream(rs.stream.color, 640, 480, rs.format.rgb8, 30)
        
        # 启动流
        profile = self.pipeline.start(config)
        
        # 获取内参
        depth_profile = rs.video_stream_profile(profile.get_stream(rs.stream.depth))
        self.depth_intrinsics = depth_profile.get_intrinsics()
        
        # 创建点云处理器
        self.pc = rs.pointcloud()
        
        # 注册事件处理器
        self.window.push_handlers(
            on_draw=self.on_draw,
            on_resize=self.on_resize,
            on_mouse_drag=self.on_mouse_drag,
            on_mouse_scroll=self.on_mouse_scroll,
            on_key_press=self.on_key_press
        )
        
        # 调度更新函数
        pyglet.clock.schedule(self.update)
        
    def on_resize(self, width, height):
        self.width, self.height = width, height
        return True
        
    def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
        # 旋转控制
        if buttons & pyglet.window.mouse.LEFT:
            self.yaw += dx * 0.5
            self.pitch += dy * 0.5
        # 平移控制
        elif buttons & pyglet.window.mouse.RIGHT:
            self.translation[0] += dx * 0.005 * self.distance
            self.translation[1] -= dy * 0.005 * self.distance
            
    def on_mouse_scroll(self, x, y, scroll_x, scroll_y):
        # 缩放控制
        self.distance -= scroll_y * 0.1
        self.distance = max(0.5, min(self.distance, 10.0))
        
    def on_key_press(self, symbol, modifiers):
        # 按键控制
        if symbol == pyglet.window.key.ESCAPE:
            self.window.close()
        elif symbol == pyglet.window.key.R:
            # 重置视角
            self.pitch, self.yaw = 0, 0
            self.distance = 2.0
            self.translation = np.array([0, 0, 0], dtype=np.float32)
        elif symbol == pyglet.window.key.S:
            # 保存点云
            if self.vertices is not None:
                self.save_pointcloud()
                
    def save_pointcloud(self):
        # 保存为PLY格式
        pass
        
    def update(self, dt):
        # 获取帧
        frames = self.pipeline.wait_for_frames()
        depth_frame = frames.get_depth_frame()
        color_frame = frames.get_color_frame()
        
        if not depth_frame or not color_frame:
            return
            
        # 计算点云
        points = self.pc.calculate(depth_frame)
        self.pc.map_to(color_frame)
        
        # 获取顶点和颜色
        vtx = np.asarray(points.get_vertices())
        tex = np.asarray(points.get_texture_coordinates())
        
        # 转换为三维坐标
        self.vertices = np.zeros((len(vtx), 3), dtype=np.float32)
        for i in range(len(vtx)):
            self.vertices[i] = [vtx[i][0], vtx[i][1], vtx[i][2]]
            
        # 获取颜色数据
        color_data = np.asarray(color_frame.get_data())
        color_h, color_w = color_data.shape[:2]
        
        # 为点云着色
        self.colors = np.zeros((len(tex), 3), dtype=np.float32)
        for i in range(len(tex)):
            u, v = int(tex[i][0] * color_w), int(tex[i][1] * color_h)
            u = np.clip(u, 0, color_w-1)
            v = np.clip(v, 0, color_h-1)
            self.colors[i] = color_data[v, u] / 255.0
            
    def on_draw(self):
        self.window.clear()
        
        # 设置视口
        gl.glViewport(0, 0, self.width, self.height)
        
        # 设置投影矩阵
        gl.glMatrixMode(gl.GL_PROJECTION)
        gl.glLoadIdentity()
        gl.gluPerspective(60, self.width / self.height, 0.01, 100)
        
        # 设置模型视图矩阵
        gl.glMatrixMode(gl.GL_MODELVIEW)
        gl.glLoadIdentity()
        
        # 应用相机变换
        gl.glTranslatef(0, 0, -self.distance)
        gl.glRotatef(self.pitch, 1, 0, 0)
        gl.glRotatef(self.yaw, 0, 1, 0)
        gl.glTranslatef(*self.translation)
        
        # 启用深度测试
        gl.glEnable(gl.GL_DEPTH_TEST)
        
        # 绘制点云
        if self.vertices is not None and self.colors is not None:
            gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
            gl.glEnableClientState(gl.GL_COLOR_ARRAY)
            
            gl.glVertexPointer(3, gl.GL_FLOAT, 0, self.vertices)
            gl.glColorPointer(3, gl.GL_FLOAT, 0, self.colors)
            
            gl.glPointSize(2)
            gl.glDrawArrays(gl.GL_POINTS, 0, len(self.vertices))
            
            gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
            gl.glDisableClientState(gl.GL_COLOR_ARRAY)
            
        # 禁用深度测试
        gl.glDisable(gl.GL_DEPTH_TEST)
        
    def run(self):
        pyglet.app.run()
        
    def close(self):
        self.pipeline.stop()
        self.window.close()

if __name__ == "__main__":
    viewer = PointCloudViewer()
    viewer.run()

3D交互核心技术

  1. 相机控制:实现旋转(左键拖动)、平移(右键拖动)、缩放(滚轮)的标准3D交互模式
  2. 点云着色:通过纹理坐标映射将彩色图像与点云对齐,实现逼真着色效果
  3. 性能优化:使用顶点数组和颜色数组批量绘制,提高渲染效率
  4. 视角重置:一键恢复初始视角,提升用户体验

实战案例:构建物体尺寸测量工具

功能需求分析

mermaid

完整实现代码

# 综合案例:基于PyQt5的物体尺寸测量工具
import sys
import numpy as np
import cv2
import pyrealsense2 as rs
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, 
                            QHBoxLayout, QLabel, QPushButton, QMessageBox,
                            QFileDialog, QTableWidget, QTableWidgetItem)
from PyQt5.QtGui import QPixmap, QImage, QPainter, QPen, QColor
from PyQt5.QtCore import Qt, QPoint

class MeasurementTool(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("RealSense 物体尺寸测量工具")
        self.setGeometry(100, 100, 1280, 800)
        
        # 初始化变量
        self.points = []
        self.measurements = []
        self.depth_scale = 0.001  # 深度单位转换(米)
        self.selected_point = -1
        
        # 配置RealSense
        self.pipeline = rs.pipeline()
        config = rs.config()
        config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
        config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
        
        # 启动相机
        profile = self.pipeline.start(config)
        
        # 获取深度比例
        depth_sensor = profile.get_device().first_depth_sensor()
        self.depth_scale = depth_sensor.get_depth_scale()
        
        # 创建对齐对象
        align_to = rs.stream.color
        self.align = rs.align(align_to)
        
        # 创建点云处理器
        self.pc = rs.pointcloud()
        
        # 创建UI
        self.setup_ui()
        
        # 启动定时器刷新
        self.timer = self.startTimer(30)
        
    def setup_ui(self):
        # 中心部件
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        main_layout = QVBoxLayout(self.central_widget)
        
        # 图像显示区域
        self.image_label = QLabel()
        self.image_label.setAlignment(Qt.AlignCenter)
        self.image_label.mousePressEvent = self.on_image_click
        main_layout.addWidget(self.image_label)
        
        # 控制面板
        control_layout = QHBoxLayout()
        
        # 按钮
        self.clear_btn = QPushButton("清除点")
        self.clear_btn.clicked.connect(self.clear_points)
        control_layout.addWidget(self.clear_btn)
        
        self.measure_btn = QPushButton("测量选中点")
        self.measure_btn.clicked.connect(self.measure_selected)
        control_layout.addWidget(self.measure_btn)
        
        self.export_btn = QPushButton("导出数据")
        self.export_btn.clicked.connect(self.export_data)
        control_layout.addWidget(self.export_btn)
        
        main_layout.addLayout(control_layout)
        
        # 测量结果表格
        self.results_table = QTableWidget()
        self.results_table.setColumnCount(4)
        self.results_table.setHorizontalHeaderLabels(["点1", "点2", "距离(mm)", "坐标"])
        main_layout.addWidget(self.results_table)
        
    def timerEvent(self, event):
        # 获取帧
        frames = self.pipeline.wait_for_frames()
        aligned_frames = self.align.process(frames)
        
        depth_frame = aligned_frames.get_depth_frame()
        color_frame = aligned_frames.get_color_frame()
        
        if not depth_frame or not color_frame:
            return
            
        # 转换为图像
        self.depth_image = np.asanyarray(depth_frame.get_data())
        color_image = np.asanyarray(color_frame.get_data())
        
        # 绘制测量点和结果
        self.draw_measurements(color_image)
        
        # 转换为QPixmap
        height, width, channel = color_image.shape
        bytes_per_line = channel * width
        q_image = QImage(color_image.data, width, height, bytes_per_line, QImage.Format_BGR888)
        self.image_label.setPixmap(QPixmap.fromImage(q_image))
        
    def draw_measurements(self, image):
        # 绘制点
        for i, (x, y) in enumerate(self.points):
            color = (0, 255, 0) if i != self.selected_point else (0, 0, 255)
            cv2.circle(image, (x, y), 5, color, -1)
            cv2.putText(image, f"P{i+1}", (x+10, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
            
        # 绘制测量线
        for i, (p1, p2, dist) in enumerate(self.measurements):
            cv2.line(image, p1, p2, (255, 0, 0), 2)
            mid_x = (p1[0] + p2[0]) // 2
            mid_y = (p1[1] + p2[1]) // 2
            cv2.putText(image, f"{dist:.1f}mm", (mid_x, mid_y), 
                       cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
            
    def on_image_click(self, event):
        # 计算图像缩放比例
        if self.image_label.pixmap() is None:
            return
            
        scale_x = self.depth_image.shape[1] / self.image_label.width()
        scale_y = self.depth_image.shape[0] / self.image_label.height()
        
        # 计算原图坐标
        x = int(event.pos().x() * scale_x)
        y = int(event.pos().y() * scale_y)
        
        # 限制坐标在图像范围内
        x = np.clip(x, 0, self.depth_image.shape[1]-1)
        y = np.clip(y, 0, self.depth_image.shape[0]-1)
        
        # 添加点
        self.points.append((x, y))
        self.selected_point = len(self.points) - 1
        
    def clear_points(self):
        self.points = []
        self.measurements = []
        self.results_table.setRowCount(0)
        
    def measure_selected(self):
        if len(self.points) < 2:
            QMessageBox.warning(self, "警告", "至少需要选择2个点")
            return
            
        # 获取选中点的3D坐标
        points_3d = []
        for (x, y) in self.points:
            # 获取深度值
            depth = self.depth_image[y, x] * self.depth_scale
            
            # 转换为3D坐标
            depth_intrinsics = rs.intrinsics()
            depth_intrinsics.width = self.depth_image.shape[1]
            depth_intrinsics.height = self.depth_image.shape[0]
            depth_intrinsics.ppx = 320  # 默认内参,实际应用中应从相机获取
            depth_intrinsics.ppy = 240
            depth_intrinsics.fx = 600  # 示例值
            depth_intrinsics.fy = 600
            depth_intrinsics.model = rs.distortion.none
            depth_intrinsics.coeffs = [0, 0, 0, 0, 0]
            
            # 计算3D坐标
            point = rs.rs2_deproject_pixel_to_point(depth_intrinsics, [x, y], depth)
            points_3d.append(point)
            
        # 计算距离
        p1 = np.array(points_3d[0])
        p2 = np.array(points_3d[1])
        distance = np.linalg.norm(p1 - p2) * 1000  # 转换为毫米
        
        # 添加到测量结果
        self.measurements.append((self.points[0], self.points[1], distance))
        
        # 更新表格
        row = self.results_table.rowCount()
        self.results_table.insertRow(row)
        self.results_table.setItem(row, 0, QTableWidgetItem(f"P1"))
        self.results_table.setItem(row, 1, QTableWidgetItem(f"P2"))
        self.results_table.setItem(row, 2, QTableWidgetItem(f"{distance:.1f}"))
        self.results_table.setItem(row, 3, QTableWidgetItem(f"{p1}, {p2}"))
        
        # 清除选中点
        self.points = []
        
    def clear_points(self):
        self.points = []
        self.selected_point = -1
        
    def export_data(self):
        if not self.measurements:
            QMessageBox.warning(self, "警告", "没有测量数据可导出")
            return
            
        # 保存到CSV文件
        filename, _ = QFileDialog.getSaveFileName(self, "导出数据", "", "CSV文件 (*.csv)")
        if filename:
            with open(filename, 'w') as f:
                f.write("点1X,点1Y,点2X,点2Y,距离(mm)\n")
                for (p1, p2, dist) in self.measurements:
                    f.write(f"{p1[0]},{p1[1]},{p2[0]},{p2[1]},{dist:.1f}\n")
            QMessageBox.information(self, "成功", f"数据已导出到 {filename}")
            
    def closeEvent(self, event):
        self.pipeline.stop()
        event.accept()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MeasurementTool()
    window.show()
    sys.exit(app.exec_())

部署与优化:构建专业级应用

性能优化策略

优化方向具体方法性能提升
数据处理使用numpy向量化操作替代循环3-5倍
渲染优化点云降采样(每n个点取1个)2-3倍
多线程将数据采集与UI更新分离避免界面卡顿
内存管理预分配数组,避免频繁内存申请1.5-2倍

跨平台部署指南

  1. Windows打包

    pip install pyinstaller
    pyinstaller --onefile --windowed --name realsense_viewer main.py
    
  2. Linux部署

    # 创建DEB包
    sudo apt install checkinstall
    python3 setup.py install --prefix=/usr/local
    checkinstall --pkgname=realsense-viewer
    
  3. 树莓派优化

    • 使用picamera库替代OpenCV进行图像显示
    • 降低分辨率至640x480
    • 禁用不必要的后处理滤镜

常见问题解决方案

问题原因解决方案
图像卡顿主线程阻塞使用多线程处理数据流
点云缺失深度值为0过滤零深度点,增加误差处理
程序崩溃相机断开连接添加异常捕获和重连机制
界面无响应计算量过大使用进度条和后台任务

总结与展望

本文系统介绍了基于Intel® RealSense™ SDK的Python GUI开发方法,从基础的图像显示到高级的3D点云交互,涵盖了环境搭建、核心技术、实战案例和部署优化等方面。通过OpenCV、PyQt5和Pyglet三个框架的对比,读者可以根据项目需求选择合适的技术路线。

未来发展方向:

  • 集成AI目标检测,实现自动测量
  • 开发Web界面,支持远程监控
  • 结合ROS系统,应用于机器人导航

掌握这些技能后,你可以快速构建工业检测、机器人视觉、增强现实等领域的深度视觉应用。立即动手实践,开启你的RealSense开发之旅吧!

点赞+收藏+关注,获取更多RealSense开发技巧和实战案例!下期预告:《RealSense多相机同步与标定技术》

【免费下载链接】librealsense Intel® RealSense™ SDK 【免费下载链接】librealsense 项目地址: https://gitcode.com/GitHub_Trending/li/librealsense

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值