基于RealSense D435相机实现手部姿态重定向

基于Intel RealSense D435相机和MediaPipe的手部姿态检测,进一步简单实现手部姿态与机器人末端的重定向,获取手部的6D坐标(包括位置和姿态)。
假设已经按照【基于 RealSenseD435i相机实现手部姿态检测】配置好所需的库和环境,并且有一个可以控制的机器人接口。

一、手部姿态重定向介绍

手部姿态重定向通常涉及将实时手部关键点映射到虚拟环境或另一个坐标系中(通常需要映射到机器人坐标系中)。可以使用以下步骤实现基本的手部姿态重定向:

  1. 获取关键点坐标:使用手部追踪库(如 MediaPipe)获取手部关键点的坐标。
    具体包括数据获取和手部特征识别。
    首先选择合适的相机,如RGB相机、深度相机(如Kinect或RealSense),或高帧率摄像头获取实时图像或深度数据;
    然后使用机器学习或深度学习算法(如YOLO、SSD等)检测图像中的手部,也可以使用现成的手部检测模型,例如MediaPipe Hands,来实现实时手部跟踪;
    最后提取手部的关键点信息,例如手指关节、掌心等。

  2. 定义目标坐标系:确定将手部姿态映射到哪个坐标系中,比如虚拟现实环境或者机器人坐标系。

  3. 姿态重定向:根据目标坐标系的需求,进行平移、旋转或缩放等变换。
    首先将2D图像坐标转换为3D空间坐标,通常需要相机内参(焦距、主点位置等),根据关键点位置计算手部的姿态(位置、方向、旋转);
    然后可以使用旋转矩阵、四元数等方式表示手部的姿态;最后将手部的当前姿态转换到机器人的目标姿态。

  4. 输出重定向后的姿态:将重定向后的坐标记录用于后续处理。

二、简单实现手部姿态与机器人末端的重定向

MediaPipe检测器可以准确定位腕部框架中21个手指关节坐标的3D关键点和图像上的2D关键点。

代码示例

import cv2
import numpy as np
import pyrealsense2 as rs
import mediapipe as mp
import time# 初始化 RealSense 管道
pipeline = rs.pipeline()
config = rs.config()
config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
pipeline.start(config)# 初始化 MediaPipe 手部模块
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(max_num_hands=2, min_detection_confidence=0.7)
mp_draw = mp.solutions.drawing_utils# 机器人控制函数(示例),具体需要根据需要通过逆解解算
def move_robot_to(position):# 在这里添加机器人控制代码print(f"移动机器人末端到位置: {position}")try:while True:# 获取图像帧frames = pipeline.wait_for_frames()color_frame = frames.get_color_frame()if not color_frame:continue# 转换为 numpy 数组color_image = np.asanyarray(color_frame.get_data())# 将图像转换为 RGB 格式rgb_image = cv2.cvtColor(color_image, cv2.COLOR_BGR2RGB)rgb_image.flags.writeable = False# 检测手部results = hands.process(rgb_image)# 将图像转换回 BGR 格式rgb_image.flags.writeable = Trueannotated_image = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2BGR)# 如果检测到手部if results.multi_hand_landmarks:for hand_landmarks in results.multi_hand_landmarks:# 绘制手部标记mp_draw.draw_landmarks(annotated_image, hand_landmarks, mp_hands.HAND_CONNECTIONS)# 获取手腕的位置(关节0)wrist = hand_landmarks.landmark[mp_hands.HandLandmark.WRIST]h, w, c = annotated_image.shapewrist_x, wrist_y = int(wrist.x * w), int(wrist.y * h)# 将手腕位置转换为机器人坐标,需要进行不同坐标系的位姿变换robot_position = (wrist_x, wrist_y)move_robot_to(robot_position)  # 移动机器人末端# 显示结果cv2.imshow('Hand Detection', annotated_image)if cv2.waitKey(1) & 0xFF == ord('q'):break
finally:# 释放资源pipeline.stop()cv2.destroyAllWindows()

代码说明

  1. 初始化 RealSense 管道:设置相机流,并启动管道。
  2. 初始化 MediaPipe:配置手部检测模块。
  3. 实时捕获与处理:在循环中捕获视频帧,并检测手部姿态。
  4. 机器人控制:通过 move_robot_to 函数模拟移动机器人末端到手腕位置,需要根据自己的机器人接口实现具体的控制代码。
  5. 显示结果:在窗口中显示手部检测的图像,按 q 键退出。

运行代码

  1. 将代码保存为 hand_pose_robot.py

  2. 连接 Intel RealSense D435 相机。

  3. 在终端中运行代码:

    python hand_pose_robot.py
    

运行结果

在这里插入图片描述将 Intel RealSense D435 相机与 MediaPipe 的手部姿态检测整合在一起,可以实现手部姿态的实时检测,并将手腕的关键点转换为相机坐标系下的空间坐标。接下来,我们将编写一个完整的示例代码,进行手部关键点坐标到机器人坐标系的转换。

三、简单实现手腕与机器人末端的坐标转换

代码示例

以下是将 Intel RealSense D435 相机与 MediaPipe 手部姿态检测结合的完整代码示例:

import cv2
import mediapipe as mp
import numpy as np
import pyrealsense2 as rs# 初始化MediaPipe手部模型
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(static_image_mode=False, max_num_hands=1, min_detection_confidence=0.7)
mp_drawing = mp.solutions.drawing_utils# 设置RealSense相机参数
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)# 启动相机流
pipeline.start(config)# 相机到机器人坐标系的转换矩阵(示例,需要根据实际情况调整)
camera_to_robot_transform = np.array([[1, 0, 0, 0],  # x轴[0, 1, 0, 0],  # y轴[0, 0, 1, 0],  # z轴[0, 0, 0, 1]   # 平移
])def wrist_to_camera_coordinates(wrist_landmark, depth_frame):# 获取深度信息depth_value = depth_frame.get_distance(int(wrist_landmark.x * 640), int(wrist_landmark.y * 480))if depth_value == 0:return None  # 如果深度值为0,返回None# 计算空间坐标x = (wrist_landmark.x * 640 - 320) * depth_value / 525.0  # 525.0是相机焦距(可根据相机参数调整)y = (wrist_landmark.y * 480 - 240) * depth_value / 525.0z = depth_valuereturn np.array([x, y, z])def main():while True:# 获取相机帧frames = pipeline.wait_for_frames()color_frame = frames.get_color_frame()depth_frame = frames.get_depth_frame()if not color_frame or not depth_frame:continue# 转换为numpy数组frame = np.asanyarray(color_frame.get_data())# RGB转换frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)results = hands.process(frame_rgb)if results.multi_hand_landmarks:for hand_landmarks in results.multi_hand_landmarks:# 提取手腕关键点wrist_landmark = hand_landmarks.landmark[mp_hands.HandLandmark.WRIST]# 转换为相机坐标系下的空间坐标wrist_coordinates = wrist_to_camera_coordinates(wrist_landmark, depth_frame)if wrist_coordinates is not None:# 映射到机器人坐标系robot_coordinates = camera_to_robot_transform @ np.append(wrist_coordinates, 1)  # 同质坐标转换# 打印机器人坐标print(f"Wrist Coordinates (Camera): {wrist_coordinates}")print(f"Wrist Coordinates (Robot): {robot_coordinates[:3]}")  # 只取x, y, z# 可视化手部关键点mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)cv2.imshow('Hand Tracking', frame)if cv2.waitKey(1) & 0xFF == 27:  # 按Esc退出break# 停止相机流pipeline.stop()cv2.destroyAllWindows()if __name__ == "__main__":main()

代码说明

  • RealSense 相机设置:使用 pyrealsense2 库来设置和启动 RealSense D435 相机的流。代码配置了颜色流和深度流。

  • MediaPipe 手部姿态检测:使用 MediaPipe 检测手部关键点,特别是手腕的位置。

  • 手腕坐标转换wrist_to_camera_coordinates 函数根据手腕的关键点和深度图计算相机坐标系下的空间坐标。

  • 坐标转换:使用转换矩阵将相机坐标系下的手腕坐标转换到机器人坐标系。需要根据实际机器人和相机的位置关系调整 camera_to_robot_transform 矩阵。

  • 可视化和输出:代码在每帧中显示检测到的手部关键点,并输出手腕在相机坐标系和机器人坐标系下的坐标。

运行代码

  1. 将代码保存为 hand_pose_robot.py
  2. 连接 Intel RealSense D435 相机。
  3. 在终端中运行代码:
python hand_pose_robot.py

运行结果

Wrist Coordinates (Camera): [0.04378617 0.0835716  0.58400005]
Wrist Coordinates (Robot): [ 0.04378617 -0.0835716   0.58400005]

四、简单实现手部的6D坐标获取

要获取手部的6D坐标(包括位置和姿态),可以通过以下步骤实现:

  1. 获取3D坐标:使用 MediaPipe 提供的手部关键点数据(例如,手腕、手指尖等),获取它们的3D坐标(x, y, z)。

  2. 计算姿态信息:姿态信息通常可以通过手部关键点的位置和方向来推断。例如,可以使用手指的相对位置和角度来表示手的朝向。你可以选择特定的关键点(如手腕和食指尖)来定义手的方向。

  3. 构造6D坐标:组合位置和姿态信息,构造6D坐标。

代码示例

以下是如何在代码中实现这一点的示例:

import cv2
import numpy as np
import pyrealsense2 as rs
import mediapipe as mp
import math# 其他部分保持不变...def calculate_orientation(hand_landmarks):# 假设使用手腕和食指尖来计算姿态wrist = hand_landmarks.landmark[mp_hands.HandLandmark.WRIST]index_finger_tip = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP]# 获取3D坐标wrist_pos = np.array([wrist.x, wrist.y, wrist.z])finger_tip_pos = np.array([index_finger_tip.x, index_finger_tip.y, index_finger_tip.z])# 计算手的方向向量direction_vector = finger_tip_pos - wrist_posdirection_vector /= np.linalg.norm(direction_vector)  # 单位化# 将方向向量转换为欧拉角(假设手向上)yaw = math.atan2(direction_vector[1], direction_vector[0])pitch = math.asin(direction_vector[2])roll = 0  # 如果不考虑手的旋转,roll可以设为0return wrist_pos, (yaw, pitch, roll)try:while True:frames = pipeline.wait_for_frames()color_frame = frames.get_color_frame()if not color_frame:continuecolor_image = np.asanyarray(color_frame.get_data())rgb_image = cv2.cvtColor(color_image, cv2.COLOR_BGR2RGB)rgb_image.flags.writeable = Falseresults = hands.process(rgb_image)rgb_image.flags.writeable = Trueannotated_image = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2BGR)if results.multi_hand_landmarks:for hand_landmarks in results.multi_hand_landmarks:mp_draw.draw_landmarks(annotated_image, hand_landmarks, mp_hands.HAND_CONNECTIONS)wrist_pos, orientation = calculate_orientation(hand_landmarks)robot_position = wrist_pos  # 机器人位置为手腕坐标move_robot_to(robot_position)  # 移动机器人末端print(f"手腕位置: {wrist_pos}, 姿态: {orientation}")cv2.imshow('Hand Detection', annotated_image)if cv2.waitKey(1) & 0xFF == ord('q'):break
finally:pipeline.stop()cv2.destroyAllWindows()

代码说明

  1. calculate_orientation 函数:计算手腕的3D位置和手的朝向(以欧拉角表示)。
  2. 姿态计算:根据手腕和食指尖的位置计算手的方向,并归一化为单位向量,从而得到姿态。
  3. 输出结果:打印手腕的位置和姿态。

运行代码

  1. 将代码保存为 hand_pose_robot_6D.py
  2. 连接 Intel RealSense D435 相机。
  3. 在终端中运行代码:
python hand_pose_robot_6D.py

运行结果

手腕位置: [ 6.16283059e-01  5.05638361e-01 -1.23956696e-07], 姿态: (-1.6486818875015121, -0.3188391517848179, 0)
手腕位置: [ 6.15322232e-01  5.09867549e-01 -1.33983647e-07], 姿态: (-1.6649436814315695, -0.3417587888604621, 0)
手腕位置: [ 6.18688941e-01  5.15018821e-01 -1.20955633e-07], 姿态: (-1.6953785334171043, -0.2905682467378848, 0)
手腕位置: [ 6.19475007e-01  5.10892391e-01 -1.25988706e-07], 姿态: (-1.7442050004258685, -0.17409076245894894, 0)
手腕位置: [ 6.22752011e-01  5.18672347e-01 -9.87428663e-08], 姿态: (-1.8722014318776006, -0.183676503807803, 0)
手腕位置: [6.27165079e-01 5.15416026e-01 8.79372877e-08], 姿态: (-2.0528003434969873, -0.07735958610038009, 0)
手腕位置: [6.26826108e-01 5.08712649e-01 1.98455922e-07], 姿态: (-2.020922761062857, -0.06753396048955623, 0)
手腕位置: [6.31548941e-01 5.09610891e-01 2.30047050e-07], 姿态: (-2.0704836718570623, 0.019604326160985164, 0)
手腕位置: [6.32204950e-01 5.19681990e-01 2.23285795e-07], 姿态: (-2.065844798885916, 0.12585902334658688, 0)
手腕位置: [6.32742882e-01 5.19853532e-01 3.06575970e-07], 姿态: (-2.056895662858401, 0.11631550222837758, 0)

通过这个方法,可以获得6D坐标(位置和姿态),适用于进一步的机器人控制和交互。确保根据具体应用需要对姿态计算进行调整。

五、总结

确保环境中已经安装了相关库,并且相机正常工作。运行后,窗口中将显示实时的手部检测结果,同时机器人末端会根据手腕位置进行重定向。可以实时监测手部动作并将其坐标转换为机器人坐标系,进而实现对机器人的控制。

在实际应用中,可能需要:

  • 根据 RealSense 相机的参数调整坐标转换公式。
  • 调整机器人坐标系的转换矩阵,以匹配相机与机器人之间的实际位置关系。
  • 增强代码的鲁棒性,处理深度数据的缺失情况。

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

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

相关文章

海口网站建设的最佳实践

海口网站建设的最佳实践 随着互联网的迅猛发展,海口的企业和个人越来越重视网站建设。一个高质量的网站不仅能提升企业形象,还能有效促进品牌传播和业务发展。以下是海口网站建设的一些最佳实践,希望能为相关从业者提供帮助。 1. 明确目标和…

一文说清楚:如何学习好K8s、OpenStack、Docker、Linux?

大家好,我是你们熟悉的-CloudJourney。在这个信息爆炸的时代,我一直致力于通过博客、公众号等平台,与大家分享关于Linux、K8S、Docker、网络、服务器以及OpenStack等前沿技术的见解与心得。然而,随着交流的深入,我逐渐…

[论文精读]TorWard: Discovery, Blocking, and Traceback of Malicious Traffic Over Tor

期刊名称:IEEE Transactions on Information Forensics and Security 发布链接:TorWard: Discovery, Blocking, and Traceback of Malicious Traffic Over Tor | IEEE Journals & Magazine | IEEE Xplore 中文译名:TorWard:…

EDM平台大比拼 用户体验与营销效果双重测评

本文评测了ZohoCampaigns、Mailchimp、Sendinblue、AWeber四款EDM平台,分别适合中小企业、多平台集成、多功能集成、初学者等需求。建议企业根据自身规模、技术水平和功能需求选择最适合的平台。 一、Zoho Campaigns 功能概述 Zoho Campaigns是Zoho旗下的一款专注…

前端框架:选择的艺术

一、简介 在现代 web 开发中,前端框架扮演着至关重要的角色。 首先,它们极大地提升了开发效率。以 React、Vue 和 Angular 为例,这些框架采用组件化的开发模式,允许开发者将页面拆分成独立的、可复用的组件。例如,在一…

学校周赛(2)

A.Minimize! 题目 思路 本题只需要遍历c的取值&#xff0c;实时更新答案即可 代码 #include<iostream> #include<algorithm> using namespace std;void todo(){int a,b;cin>>a>>b;int ansINT_MAX;for(int ca;c<b;c){ansmin(ans,(c-a)(b-c));}co…

面试题:MySQL你用过WITH吗?领免费激活码

感谢Java面试教程的Java多线程文章&#xff0c;点击查看>原文 Java面试教程&#xff0c;发mmm116可获取IDEA-jihuoma 在MySQL中&#xff0c;WITH子句用于定义临时表或视图&#xff0c;也称为公共表表达式&#xff08;CTE&#xff09;。它允许你在一个查询中定义一个临时结果…

耳机检测系统源码分享

耳机检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

spring-boot 整合 mybatis

文章目录 Spring boot 整合Mybatis将数据返回到浏览器1、准备数据2. 创建一个 pojo 包&#xff0c;创建User实体类3. 创建一个mapper包&#xff0c;写一个UserMapper接口4. 创建一个service包&#xff0c;写一个UserService接口。5. 在 Service 包下创建一个子包&#xff0c;im…

CSS 的背景样式

1.1 背景颜色 1.2 背景图片 1.3 背景平铺 1.4 背景图片位置 1.4.1 方位名词 1.4.2 精确单位 1.4.3 混合单位 1.5 背景图像固定 1.6 背景复合写法 1.7 背景色半透明 1.8 总结

SpringCloud-07 GateWay01 网关技术

Spring Cloud Gateway组件的核心是一系列的过滤器&#xff0c;通过这些过滤器可以将客户端发送的请求转发(路由)到对应的微服务。 Spring Cloud Gateway是加在整个微服务最前沿的防火墙和代理器&#xff0c;隐藏微服务结点IP端口信息&#xff0c;从而加强安全保护。Spring Clou…

Flink 结合kafka 实现端到端的一致性原理

Kafka 事务实现原理 Flink checkpoint 结合kafka 实现端到端的一致性 CASE 分析 1.checkpoint 不成功情况会发生啥&#xff1f; checkpoint 不成功&#xff0c;事务就不会提交&#xff0c;如果checkpoint 一直不成功&#xff0c;任务重启或失败&#xff0c;则会终止事务。从整…

DriveVLM 论文学习

论文链接&#xff1a;https://arxiv.org/abs/2402.12289 解决了什么问题&#xff1f; 自动驾驶对交通行业有着革命性的作用&#xff0c;实现 FSD 的一个主要障碍就是场景理解。场景理解涉及在复杂且不可预测的环境中进行导航&#xff0c;这些环境可能包括恶劣的天气条件、复杂…

每日OJ题_牛客_HJ108求最小公倍数_C++_Java

目录 牛客_HJ108求最小公倍数_C_Java 题目解析 C代码 Java代码 牛客_HJ108求最小公倍数_C_Java 求最小公倍数_牛客题霸_牛客网 题目解析 A 和 B 的最小公倍数 A * B / 两者的最大公约数。最大公约数&#xff1a;辗转相除法。 C代码 #include <iostream> #includ…

【车联网安全】车端网络攻击及检测的框架/模型

参考标准&#xff1a; 《汽车数据安全管理若干规定&#xff08;试行&#xff09;》ISO/SAE 21434《道路车辆 网络安全工程》威胁分析和风险评估&#xff08;TARA&#xff09;ISO/DIS 24089R155法规的国标转换&#xff1a;《汽车整车信息安全技术要求》&#xff08;UN R155&…

Kafka:架构与核心机制

Apache Kafka 是一种高吞吐量的分布式消息队列&#xff0c;广泛应用于实时数据流处理和大数据架构中。本文将详细探讨 Kafka 的架构、Replica 管理、消息读取、分区策略、可靠性保障等核心机制。 1. Kafka 的架构 1.1 组件概述 Kafka 的架构由多个组件构成&#xff0c;主要包…

Ps:打开与置入

在 Adobe Photoshop 中&#xff0c;理解不同的“打开”和“置入”命令及其用途&#xff0c;可以根据不同的需求选择最佳方式来管理和编辑图像文件。 ◆ ◆ ◆ 打开 1、Ps菜单&#xff1a;文件/打开 File/Open 快捷键&#xff1a;Ctrl O 用于直接打开现有的图像文件。 打开的…

音视频入门基础:FLV专题(3)——FLV header简介

一、引言 本文对FLV格式的FLV header进行简介&#xff0c;FLV文件的开头就是FLV header。 进行简介之前&#xff0c;请各位先从《音视频入门基础&#xff1a;FLV专题&#xff08;1&#xff09;——FLV官方文档下载》下载FLV的官方文档《video_file_format_spec_v10_1.pdf》和…

【Python】FeinCMS:轻量级且可扩展的Django内容管理系统

在互联网飞速发展的今天&#xff0c;内容管理系统&#xff08;CMS&#xff09;成为了网站开发中的核心工具&#xff0c;尤其对于需要频繁更新内容的企业和个人站点而言&#xff0c;CMS 提供了极大的便利。市场上有许多不同的 CMS 工具可供选择&#xff0c;其中基于 Django 框架…

从Web2到Web3:探索下一代互联网的无限可能性

互联网经历了从Web1到Web2的重大变革&#xff0c;现在正迈向Web3。Web2通过社交媒体、电子商务和内容平台改变了我们的数字生活&#xff0c;但同时也伴随着中心化平台的垄断和用户数据被广泛控制的问题。而Web3的出现&#xff0c;则试图通过去中心化技术解决这些挑战&#xff0…