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

文章目录

  • 奥比中光深度相机(二):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.mzph.cn/news/785420.shtml

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

相关文章

HarmonyOS实战开发-如何实现一个简单的健康生活应用(上)

介绍 本篇Codelab介绍了如何实现一个简单的健康生活应用&#xff0c;主要功能包括&#xff1a; 用户可以创建最多6个健康生活任务&#xff08;早起&#xff0c;喝水&#xff0c;吃苹果&#xff0c;每日微笑&#xff0c;刷牙&#xff0c;早睡&#xff09;&#xff0c;并设置任…

BabySQL【2019极客大挑战】

知识点&#xff1a; 功能分析 登录界面一般是 where username and password 可以从username出手&#xff0c;注释掉and语句单引号闭合绕过 通过测试和报错信息发现是一个单引号读取输入可以单引号闭合绕过关键字过滤 or and 过滤 || &&替换双写绕过select from wher…

【leetcode】力扣简单题两数之和

题目 思路 代码实现 #include<iostream> #include<unordered_map>using namespace std;class Solution { public:vector<int> TwoNumber(const vector<int>& nums, int target){vector<int> number_vector;unordered_map<int, int> …

【Linux】常见命令

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 常用命令 1. ls2. pwd3. cd4. touch5. cat6. mkdir7. rm8. cp9. mv10. tail11. vim12.…

TCP粘包是怎么回事,如何处理?

还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#xff0c;webgl&#xff0c;ech…

基于《2023腾讯云容器和函数计算技术实践精选集》—探索腾讯云TKE的Docker容器、Serverless和微服务优势

重剑无锋&#xff0c;大巧不工。 ——金庸 腾讯云TKE&#xff0c;全称Tencent Kubernetes Engine&#xff0c;是一种完全托管式的容器服务。它可以帮助用户快速、高效地部署和管理Kubernetes集群&#xff0c;并提供一系列与之相关的云服务&#xff0c;如负载均衡、云硬盘、对象…

OSPF---开放式最短路径优先协议

1. OSPF描述 OSPF协议是一种链路状态协议。每个路由器负责发现、维护与邻居的关系&#xff0c;并将已知的邻居列表和链路费用LSU报文描述&#xff0c;通过可靠的泛洪与自治系统AS内的其他路由器周期性交互&#xff0c;学习到整个自治系统的网络拓扑结构;并通过自治系统边界的路…

掼蛋游戏规则

1、牌型&#xff1a;单牌、对牌、三张牌、三带二、顺子、同花顺、钢板&#xff08;例&#xff1a; 222333、444555&#xff09;、炸弹&#xff08;4涨以上相同的牌&#xff09;、三连对 2、牌大小&#xff1a;大王&#xff0c;小王&#xff0c;级牌&#xff0c;A&#xff0c;…

从学习海底捞到学习巴奴,中国餐饮带洋快餐重归“产品主义”

俗话说“民以食为天”&#xff0c;吃饭一向是国人的头等大事&#xff0c;餐饮业也是经济的强劲助推力。新世纪以来&#xff0c;餐饮业不断讲述着热辣滚烫的商业故事。 2006年&#xff0c;拥有“必胜客”、“肯德基”等品牌的餐饮巨头百胜集团&#xff0c;组织两百多名区域经理…

太阳能光伏发电应用场景有哪些?

随着全球能源结构的转型和环保意识的提升&#xff0c;太阳能光伏发电作为一种清洁、可再生的能源形式&#xff0c;其应用场景正日益广泛。下面&#xff0c;我们将详细探讨太阳能光伏发电的主要应用场景。 首先&#xff0c;工业领域是太阳能光伏发电的重要应用领域。工业厂房通常…

EasyCVR视频汇聚平台海康Ehome2.0与5.0设备接入时的配置区别

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

Nessus【部署 01】Linux环境部署漏洞扫描工具Nessus最新版详细过程分享(下载+安装+注册+激活)

Nessus最新版详细部署过程分享 1. 获取激活码2.主程序下载安装启动2.1 下载2.2安装2.3 启动 3.许可证及插件3.1 许可证获取3.2 插件安装 4.安装总结 Nessus官方网站&#xff1a; https://www.tenable.com/products/nessus/nessus-essentials 及介绍&#xff1a; 国际数据公司&…

编程语言 MoonBit 本周有超多重磅更新等你来探索:expect 测试添加 inspect 函数,还有……

MoonBit 更新 1. expect 测试添加 inspect 函数 expect 测试添加针对 Show 接口的 inspect 函数&#xff0c;签名如下&#xff1a; pub fn inspect(obj: Show,~content: String "",~loc: SourceLoc _,~args_loc: ArgsLoc _ ) -> Result[Unit, String]⚠️ 此…

C++函数重载引用

函数重载 自然语言中&#xff0c;一个词可以有多重含义&#xff0c;人们可以通过上下文来判断该词真实的含义&#xff0c;即该词被重载了。比如&#xff1a;以前有一个笑话&#xff0c;国有两个体育项目大家根本不用看&#xff0c;也不用担心。一个是乒乓球&#xff0c;一个是男…

Mybatis(3) web项目

web项目 1、准备2、分析3、 MyBatis对象作用域以及事务问题4、问题 实现一个转账系统 1、准备 ①准备一个web模块 在这里使用了maven archetype&#xff0c;选择web 之后会生成 一个web模块&#xff0c;但是不同的版本可能不同&#xff0c;在这里我就没有java和resources目录&…

KUKA机器人更改时间和HMI最小化设置

在使用 KUKA 机器人时&#xff0c;示教器上左边有个“表”的图标&#xff0c;点一下就会显示时间。但一般不准&#xff0c;想要更改时间可以通过HMI最小化后进行更改设置。更改时间需要将示教器界面最小化&#xff0c;也就是进入Windows 界面。通过以下步骤可以进行设置&#x…

ThreadLocal的基本使用

一、ThreadLocal的介绍 ThreadLocal 是 Java 中的一个类&#xff0c;它提供了线程局部变量的功能。线程局部变量是指每个线程拥有自己独立的变量副本&#xff0c;这些变量在不同的线程中互不影响。ThreadLocal 提供了一种在多线程环境下&#xff0c;每个线程都可以独立访问自己…

多叉树题目:N 叉树的最大深度

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;N 叉树的最大深度 出处&#xff1a;559. N 叉树的最大深度 难度 3 级 题目描述 要求 给定一个 N 叉树&#xf…

算法6.4-6.6DFS

一个不知名大学生&#xff0c;江湖人称菜狗 original author: Jacky Li Email : 3435673055qq.com Time of completion&#xff1a;2024.03.27 Last edited: 2024.03.27 目录 算法6.4-6.6DFS 第1关&#xff1a;算法6.5采用邻接矩阵表示图的深搜 任务描述 相关知识 编程要求…

2024银行业最新数字化转型的方法与路径

银行业数字化转型是一场由思想到行动、由顶层到基层、由内部到外部的深刻变革&#xff0c; 需要科学方法论的指导。在推动体系性重塑、开放生态建设、业务科技融合、基础设施升 级以及体制机制变革等探索和实践中&#xff0c;银行业逐步形成从顶层设计到数字化能力建设&#xf…