奥比中光深度相机(二):PyQt5实现打开深度摄像头功能

news/2024/6/20 14:55:06/文章来源:https://blog.csdn.net/WYKB_Mr_Q/article/details/137084563

文章目录

  • 奥比中光深度相机(二):PyQt5实现打开深度摄像头功能
    • 官方给出的调用深度相机源码
      • 环境精炼
    • UI界面设计
    • 逻辑代码构建
      • 槽函数连接
      • 提取视频流
      • 在界面中显示深度视频流
      • 注意
      • 关闭相机
    • 总体代码
    • 效果演示
      • 运行main.py代码
      • 选择相机
      • 打开摄像头
      • 关闭摄像头

奥比中光深度相机(二):PyQt5实现打开深度摄像头功能

PyQt5实现打开可见光相机摄像头的功能,我们之前已经介绍过了,具体可参考:https://blog.csdn.net/WYKB_Mr_Q/article/details/129827685

上篇文章中我们介绍了奥比中光深度相机基于Python的环境配置部分。具体可参考:https://blog.csdn.net/WYKB_Mr_Q/article/details/137040226

这篇文章我们在配置好Python环境的基础上,使用PyQt5写个界面,并且设计逻辑,通过点击一个设计好的按钮来打开深度相机。深度相机的打开方法和可见光相机的打开方法略有不同,可见光相机可以利用OpenCV来直接调用,奥比中光深度相机主要是利用官方给出的SDK源码来调用。本文中,我们借鉴官方源码,将调用深度相机的主要代码提取出来,并和我们自己写的代码结合,实现在PyQt5界面中通过点击按钮打开深度相机。

官方给出的调用深度相机源码

官方给出了打开深度相机的Python SDK源码,链接为:https://github.com/orbbec/pyorbbecsdk
在这里插入图片描述

其中也包含了一些.py示例文件,存储在pyorbbecsdk/examples文件夹中,我们找到 “depth_viewer.py” 文件,该文件的主要作用是为了调用深度相机,显示深度图像的。咱们可以先连接上奥比中光深度相机,运行一下该代码试一试,看看是否能够正常运行,展示出深度视频流。如果一切正常,你就可以看到如下界面了。

在这里插入图片描述

下面部分是 “depth_viewer.py” 文件的源代码:

from pyorbbecsdk import Pipeline
from pyorbbecsdk import Config
from pyorbbecsdk import OBSensorType, OBFormat
from pyorbbecsdk import OBError
import cv2
import numpy as np
import timeESC_KEY = 27
PRINT_INTERVAL = 1  # seconds
MIN_DEPTH = 20  # 20mm
MAX_DEPTH = 10000  # 10000mm# 管理时间流,这部分不用管
class TemporalFilter:def __init__(self, alpha):self.alpha = alphaself.previous_frame = Nonedef process(self, frame):if self.previous_frame is None:result = frameelse:result = cv2.addWeighted(frame, self.alpha, self.previous_frame, 1 - self.alpha, 0)self.previous_frame = resultreturn resultdef main():# 配置深度相机文件config = Config()pipeline = Pipeline()temporal_filter = TemporalFilter(alpha=0.5)try:# 调用深度摄像头profile_list = pipeline.get_stream_profile_list(OBSensorType.DEPTH_SENSOR)assert profile_list is not Nonetry:# 配置深度视频流参数,包括视频帧长宽,视频流格式,以及每秒采集的视频帧数depth_profile = profile_list.get_video_stream_profile(640, 0, OBFormat.Y16, 30)except OBError as e:print("Error: ", e)depth_profile = profile_list.get_default_video_stream_profile()assert depth_profile is not Noneprint("depth profile: ", type(depth_profile))config.enable_stream(depth_profile)except Exception as e:print(e)returnpipeline.start(config)last_print_time = time.time()while True:try:frames = pipeline.wait_for_frames(100)if frames is None:continuedepth_frame = frames.get_depth_frame()if depth_frame is None:continuewidth = depth_frame.get_width()height = depth_frame.get_height()scale = depth_frame.get_depth_scale()depth_data = np.frombuffer(depth_frame.get_data(), dtype=np.uint16)depth_data = depth_data.reshape((height, width))depth_data = depth_data.astype(np.float32) * scaledepth_data = np.where((depth_data > MIN_DEPTH) & (depth_data < MAX_DEPTH), depth_data, 0)depth_data = depth_data.astype(np.uint16)# Apply temporal filteringdepth_data = temporal_filter.process(depth_data)center_y = int(height / 2)center_x = int(width / 2)center_distance = depth_data[center_y, center_x]current_time = time.time()if current_time - last_print_time >= PRINT_INTERVAL:print("center distance: ", center_distance)last_print_time = current_timedepth_image = cv2.normalize(depth_data, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)depth_image = cv2.applyColorMap(depth_image, cv2.COLORMAP_JET)cv2.imshow("Depth Viewer", depth_image)key = cv2.waitKey(1)if key == ord('q') or key == ESC_KEY:breakexcept KeyboardInterrupt:breakpipeline.stop()if __name__ == "__main__":main()

我们主要是想将调用奥比中光深度相机的关键部分提取出来,并应用在我们自己的代码中。

环境精炼

由于官方给的SDK源码文件较多,如果全部复制到我们的项目中,显得项目很臃肿。
经过我们不断的尝试和测试,发现如果要正常调用深度相机,正常运行 “depth_viewer.py” 文件,只需要将 “OrbbecSDK.dll” 和 “pyorbbecsdk.pyd” 文件复制出去就可以。

在这里插入图片描述

就是下面这三个文件在一个文件夹里,就可以正常调用深度相机了,其余官方提供的文件都可以不要了。这样看起来是不是简单多了?

在这里插入图片描述

UI界面设计

这里主要参考我之前的博客,https://blog.csdn.net/WYKB_Mr_Q/article/details/129827685,不再做详细介绍。
我们将构建的ui代码放置到ui_code文件夹里,命名为depth_camera.py,我们这里做一个如下简单的界面做测试:

在这里插入图片描述

逻辑代码构建

槽函数连接

通过以下两行代码,实现点击按钮与函数功能的连接。

self.pushButton.clicked.connect(self.open_camera)      # 点击第一个按钮运行打开摄像头的函数
self.pushButton_2.clicked.connect(self.close_camera)   # 点击第二个按钮运行关闭摄像头的函数

提取视频流

通过以下代码可以实现视频流的调用,并将深度视频帧转化为伪彩色图像。

self.config = Config()
self.pipeline = Pipeline()
# 获取深度摄像头的所有流配置,包括流分辨率、帧速率和帧格式
profile_list = self.pipeline.get_stream_profile_list(OBSensorType.DEPTH_SENSOR)
# 选择分辨率打开流
depth_profile = profile_list.get_video_stream_profile(1280, 800, OBFormat.Y16, 10)
self.config.enable_stream(depth_profile)
self.pipeline.start(self.config)
self.condition = True
while self.condition:try:# 以阻塞方式等待数据帧,数据帧是包含配置中启用的所有流的帧数据的复合帧,并将帧等待超时设置为 100msframes = self.pipeline.wait_for_frames(100)if frames is None:continuedepth_frame = frames.get_depth_frame()if depth_frame is None:continuewidth = depth_frame.get_width()height = depth_frame.get_height()scale = depth_frame.get_depth_scale()depth_data = np.frombuffer(depth_frame.get_data(), dtype=np.uint16)depth_data = depth_data.reshape((height, width))depth_data = depth_data.astype(np.float32) * scaledepth_data = np.where((depth_data > 20) & (depth_data < 10000), depth_data, 0)depth_data = depth_data.astype(np.uint16)# 将数据转化为伪彩色图像depth_image = cv2.normalize(depth_data, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)depth_image = cv2.applyColorMap(depth_image, cv2.COLORMAP_JET)

在界面中显示深度视频流

我们主要通过保存当前视频帧,并读取展示视频帧的方式显示视频流。以下函数可以实现视频帧保存本地,读取并居中显示到设计好的界面上。

# 展示伪彩色图像功能函数
def show_pic_func(self, jet_image):cv2.imwrite("./read_image_copy.png", jet_image)img = QPixmap("./read_image_copy.png")w = img.width()h = img.height()ratio = max(w / self.label.width(), h / self.label.height())img.setDevicePixelRatio(ratio)self.label.setAlignment(Qt.AlignCenter)self.label.setPixmap(img)

注意

在显示视频帧时,需要调用cv2.waitkey()函数,不然显示出来的视频帧是灰色的,看不到图像。

self.key = cv2.waitKey(1)
if self.key == ord('q') or self.key == 27:break

关闭相机

关闭相机主要依靠pipeline.stop()函数实现,由于我们在打开摄像头时利用了 self.condition 的值,并将其设置为True,因此这里我们需要将其设置为False来终止循环语句。

# 关闭相机
def close_camera(self):self.condition = Falseself.pipeline.stop()# 将相机id设置为Noneself.CAM_NUM = Noneself.pushButton.setEnabled(True)self.pushButton_2.setEnabled(False)

总体代码

注意我们调用了ui界面设计生成的.py文件,命名为depth_camera.py,并放置到ui_code文件夹中,所以我们这里的调用代码为from ui_code.depth_camera import Ui_MainWindow,这里根据自己的命名做对应的更改。

import sys
from pyorbbecsdk import Pipeline
from pyorbbecsdk import Config
from pyorbbecsdk import OBSensorType, OBFormat
from pyorbbecsdk import OBError
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import cv2
import numpy as np
import time
from ui_code.depth_camera import Ui_MainWindowclass MainWindow(QMainWindow, Ui_MainWindow):def __init__(self, parent=None):super(MainWindow, self).__init__(parent)# UI界面self.setupUi(self)self.CAM_NUM = 0self.background()self.condition = Nonedef background(self):self.pushButton.clicked.connect(self.open_camera)self.pushButton_2.clicked.connect(self.close_camera)self.pushButton.setEnabled(True)# 初始状态不能关闭摄像头self.pushButton_2.setEnabled(False)# 展示伪彩色图像功能函数def show_pic_func(self, jet_image):cv2.imwrite("./read_image_copy.png", jet_image)img = QPixmap("./read_image_copy.png")w = img.width()h = img.height()ratio = max(w / self.label.width(), h / self.label.height())img.setDevicePixelRatio(ratio)self.label.setAlignment(Qt.AlignCenter)self.label.setPixmap(img)def temporal_filter(self, frame, alpha, previous_frame=None):if previous_frame is None:result = frameelse:result = cv2.addWeighted(frame, alpha, previous_frame, 1 - alpha, 0)previous_frame = resultreturn resultdef open_camera(self):self.label.setEnabled(True)# 选择相机型号self.CAM_NUM = self.comboBox.currentIndex()# 支持奥比中光相机if self.CAM_NUM == 0:# 可以关闭摄像头self.pushButton_2.setEnabled(True)self.pushButton.setEnabled(False)self.config = Config()self.pipeline = Pipeline()# 获取深度摄像头的所有流配置,包括流分辨率、帧速率和帧格式profile_list = self.pipeline.get_stream_profile_list(OBSensorType.DEPTH_SENSOR)# 选择分辨率打开流depth_profile = profile_list.get_video_stream_profile(1280, 800, OBFormat.Y16, 10)self.config.enable_stream(depth_profile)self.pipeline.start(self.config)self.condition = Truewhile self.condition:try:# 以阻塞方式等待数据帧,数据帧是包含配置中启用的所有流的帧数据的复合帧,并将帧等待超时设置为 100msframes = self.pipeline.wait_for_frames(100)if frames is None:continuedepth_frame = frames.get_depth_frame()if depth_frame is None:continuewidth = depth_frame.get_width()height = depth_frame.get_height()scale = depth_frame.get_depth_scale()depth_data = np.frombuffer(depth_frame.get_data(), dtype=np.uint16)depth_data = depth_data.reshape((height, width))depth_data = depth_data.astype(np.float32) * scaledepth_data = np.where((depth_data > 20) & (depth_data < 10000), depth_data, 0)depth_data = depth_data.astype(np.uint16)# Apply temporal filteringdepth_data = self.temporal_filter(depth_data, alpha=0.5)depth_image = cv2.normalize(depth_data, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)depth_image = cv2.applyColorMap(depth_image, cv2.COLORMAP_JET)# 展示伪彩色深度图像self.show_pic_func(depth_image)self.key = cv2.waitKey(1)if self.key == ord('q') or self.key == 27:breakexcept KeyboardInterrupt:breakelse:QMessageBox.information(self, "警告", "我们暂时仅支持奥比中光,请选择奥比中光相机!", QMessageBox.Ok)# 关闭相机def close_camera(self):self.condition = Falseself.pipeline.stop()self.CAM_NUM = Noneself.pushButton.setEnabled(True)self.pushButton_2.setEnabled(False)if __name__ == "__main__":app = QApplication(sys.argv)main = MainWindow()main.show()sys.exit(app.exec_())

效果演示

运行main.py代码

在这里插入图片描述

选择相机

在这里插入图片描述

打开摄像头

在这里插入图片描述

关闭摄像头

在这里插入图片描述

该专栏博文地址:

界面开发(1) — PyQt5环境配置
界面开发(2)— 使用PyQt5制作用户登陆界面
界面开发(3)— PyQt5用户登录界面连接数据库
界面开发(4)— PyQt5实现打开图像及视频播放功能
界面开发(5)— PyQt5实现打开摄像头采集视频功能
奥比中光深度相机(一) — 环境配置

日常学习记录,一起交流讨论吧!侵权联系~

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

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

相关文章

NSSCTF Round#20 Basic 真亦假,假亦真 CSDN_To_PDF V1.2 出题笔记 (附wp+源码)

真亦假&#xff0c;假亦真 简介&#xff1a;java伪造php一句话马。实则信息泄露一扫就出&#xff0c;flag在/flag里面。 题目描述&#xff1a;开开心心签个到吧&#xff0c;祝各位师傅们好运~ 静态flag&#xff1a;NSS{Checkin_h4v3_4_g00D_tINNe!} /路由显示 <?php e…

6、Cocos Creator 2D 渲染组件:​Sprite 组件​

Sprite 组件 Sprite&#xff08;精灵&#xff09;是 2D/3D 游戏最常见的显示图像的方式&#xff0c;在节点上添加 Sprite 组件&#xff0c;就可以在场景中显示项目资源中的图片。 属性功能说明Type渲染模式&#xff0c;包括普通&#xff08;Simple&#xff09;、九宫格&#x…

源支付V7开源版2.99,修复各种提示错误

源支付V7开源版2.99&#xff0c;修复各种提示错误 加密说明&#xff1a;200拿来的&#xff0c;只有8.1这个文件加密&#xff0c;其他文件无任何加密&#xff0c;已修复各种提示错误 测试其他开源版安装提示错误&#xff0c;有几个文件是加密的 注&#xff1a;开发不易&#…

枚举---算法

1、定义 枚举算法&#xff1a;也称之为穷举算法&#xff0c;这种算法就是在解决问题的时候去使用所有的方式去解决这个问题&#xff0c;会通过推理去考虑事件发生的每一种可能&#xff0c;最后推导出结果。优点&#xff1a;简单粗暴&#xff0c;它暴力的枚举所有可能&#xff…

Linux 动静态库的制作,使用和加载

Linux 动静态库的制作,使用和加载 一.前置说明1.mylib.h2.mylib.c3.mymath.h mymath.c4.如何制作库 二.动静态库的制作1.静态库的制作1.制作2.使用一下静态库,验证是否成功打包 2.动态库的制作1.编译.c源文件文件生成.o目标文件2.打包生成动态库3.编写makefile文件,自动化制作动…

Spring 整合 Log4j2日志框架

1. Log4j2日志概述 在项目开发中&#xff0c;日志十分的重要&#xff0c;不管是记录运行情况还是定位线上问题&#xff0c;都离不开对日志的分析。日志记录了系统行为的时间、地点、状态等相关信息&#xff0c;能够帮助我们了解并监控系统状态&#xff0c;在发生错误或者接近某…

Go语言流程控制

条件语句需要开发者通过指定一个或多个条件&#xff0c;并通过测试条件是否为true来决定是否执行指定语句&#xff0c;并在条件为false的情况下执行另外的语句。 Go语言提供了一下几种条件判断语句 一. 条件语句if 1.1 if语句由一个布尔表达式后紧跟一个或多个语句组成 语法&a…

如何在Portainer中创建Nginx服务并搭建静态站点实现公网访问本地网站

文章目录 前言1. 安装Portainer1.1 访问Portainer Web界面 2. 使用Portainer创建Nginx容器3. 将Web静态站点实现公网访问4. 配置Web站点公网访问地址4.1公网访问Web站点 5. 固定Web静态站点公网地址6. 固定公网地址访问Web静态站点 前言 Portainer是一个开源的Docker轻量级可视…

牛牛排队伍

有 n 个人排队&#xff0c;1 号排在 2 号前面&#xff0c;2 号排在 3 号前面&#xff0c;…&#xff0c;以此类推 n−1 号排在 n 号前面。在这个过程中&#xff0c;偶尔老师会把某个人叫走&#xff0c;叫走之后这个人就离开了队伍&#xff0c;假设本来 a排在 b 前面&#xff0c…

SiameseRPN原理详解(个人学习笔记)

参考资源&#xff1a; 视觉目标跟踪SiamRPNSiameseRPN详解CVPR2018视觉目标跟踪之 SiameseRPN 目录&#xff09; 1. 模型架构1.1 Siamese Network1.2 RPN 2. 模型训练2.1 损失函数2.2 端到端训练2.3 正负样本选择 3. 跟踪阶段总结 SiamRPN是在SiamFC的基础上进行改进而得到的一…

Adobe ColdFusion 任意文件读取漏洞复现(CVE-2024-20767)

0x01 产品简介 Adobe ColdFusion是美国奥多比(Adobe)公司的一套快速应用程序开发平台。该平台包括集成开发环境和脚本语言,将可扩展、改变游戏规则且可靠的产品的愿景变为现实。 0x02 漏洞概述 由于 Adobe ColdFusion 的访问控制不当,未经身份认证的远程攻击者可以构造恶…

Ubuntu20.04安装MatlabR2018a

一、安装包 安装包下载链接 提取码&#xff1a;kve2 网上相关教程很多&#xff0c;此处仅作为安装软件记录&#xff0c;方便后续软件重装&#xff0c;大家按需取用。 二、安装 1. 相关文件一览 下载并解压文件后&#xff0c;如下图所示&#xff1a; 2. 挂载镜像并安装 2…

服务器被CC攻击之后怎么办?

1.取消域名绑定取消域名绑定后Web服务器的CPU能够马上恢复正常状态&#xff0c;通过IP进行访问连接一切正常。但是不足之处也很明显&#xff0c;取消或者更改域名对于别人的访问带来了不变&#xff0c;另外&#xff0c;对于针对IP的CC攻击它是无效的&#xff0c;就算更换域名攻…

【WEEK5】 【DAY5】DML语言【中文版】

2024.3.29 Friday 目录 3.DML语言3.1.外键&#xff08;了解&#xff09;3.1.1.概念3.1.2.作用3.1.3.添加&#xff08;书写&#xff09;外键的几种方法3.1.3.1.创建表时直接在主动引用的表里写&#xff08;被引用的表的被引用的部分&#xff09;3.1.3.2.先创建表后修改表以添加…

unity 打包安卓错误汇集

Failed to find target with hash string "android-34’ in: D:Pr 他说找不到sdk34level的我用as打开后卸载又重装&#xff0c;最后解决了 我放到Plugins/Android/下面的Java代码没有被编译 这个不知道为什么。我故意把代码写的有问题&#xff0c;会报错那种&#xff…

认识docker

认识docker 1.镜像和容器2.MySQL镜像命令解读3.docker常用命令4.数据挂载&#xff08;1&#xff09;数据卷&#xff08;2&#xff09;本地目录挂载 5.自定义镜像&#xff08;1&#xff09;Dockerfile 6.容器网络互连7、参考 1.镜像和容器 当我们利用 Docker 安装应用时&#x…

面试题 之 webpack

1.说说你对webpack理解&#xff1f;解决什么问题&#xff1f; Webpack 是实现前端项目的模块化&#xff0c;用于现代 JavaScript 应用程序的静态模块打包工具&#xff0c;被webpack 直接引用的资源打包进 bunde.js的资源&#xff0c;当webpack 处理应用程序时,它会在内部构建一…

Mysql数据库:故障分析与配置优化

目录 前言 一、Mysql逻辑架构图 二、Mysql单实例常见故障 1、无法通过套接字连接到本地MySQL服务器 2、用户rootlocalhost访问被拒绝 3、远程连接数据库时连接很慢 4、无法打开以MYI结尾的索引文件 5、超出最大连接错误数量限制 6、连接过多 7、配置文件/etc/my.cnf权…

SmartChart的部署以及可能遇见的报错解决方案

简介 数据可视化是一种将数据转化为图形的技术&#xff0c;可以帮助人们更好地理解和分析数据。但是&#xff0c;传统的数据可视化开发往往需要编写大量的代码&#xff0c;或者使用复杂的拖拽工具&#xff0c;不仅耗时耗力&#xff0c;而且难以实现个性化的需求。有没有一种更…

《VMamba》论文笔记

原文链接&#xff1a; [2401.10166] VMamba: Visual State Space Model (arxiv.org) 原文笔记&#xff1a; What&#xff1a; VMamba: Visual State Space Model Why&#xff1a; 多年以来CNN和VIT作为视觉特征提取的主流框架 CNN具有模型简单&#xff0c;共享权重&…