首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【机器人】Graspness 端到端抓取点估计 | 环境搭建 | 模型推理测试

  • 25-02-18 21:00
  • 3849
  • 9209
blog.csdn.net

在复杂场景中实现抓取检测,Graspness是一种端到端的方法;

输入点云数据,输出抓取角度、抓取深度、夹具宽度等信息。

开源地址:https://github.com/rhett-chen/graspness_implementation?tab=readme-ov-file

论文地址:Graspness Discovery in Clutters for Fast and Accurate Grasp Detection

目录

1、准备GPU加速环境

2、安装torch和cudatoolkit

3、安装Graspness相关依赖库

4、安装MinkowskiEngine

5、安装pointnet2和knn

6、安装graspnetAPI 

7、模型推理——抓取点估计


1、准备GPU加速环境

推荐在Conda环境中搭建环境,方便不同项目的管理~ 

首先需要安装好Nvidia 显卡驱动,后面还要安装CUDA11.1

输入命令:nvidia-smi,能看到显卡信息,说明Nvidia 显卡驱动安装好了

然后需要单独安装CUDA11.1了,上面虽然安装了CUDA12.2也不影响的

各种CUDA版本:https://developer.nvidia.com/cuda-toolkit-archive

CUDA11.1下载地址:https://developer.nvidia.com/cuda-11.1.0-download-archive

然后根据电脑的系统(Linux)、CPU类型,选择runfile方式

然后下载cuda_11.1.0_455.23.05_linux.run文件

wget https://developer.download.nvidia.com/compute/cuda/11.1.0/local_installers/cuda_11.1.0_455.23.05_linux.run

开始安装

sudo sh cuda_11.1.0_455.23.05_linux.run

来到下面的界面,点击“Continue”

输入“accept”

下面是关键,在455.23.05这里“回车”,取消安装;

这里X是表示需要安装的,我们只需安装CUDA11相关的即可

安装完成后,能看到/usr/local/cuda-11.1目录啦

  1. (base) lgp@lgp-MS-7E07:~/2024_project$ ls /usr/local/cuda-11.1
  2. bin EULA.txt libnvvp nsight-systems-2020.3.4 nvvm samples targets
  3. DOCS extras nsight-compute-2020.2.0 nvml README src tools

参考1:https://blog.csdn.net/weixin_37926734/article/details/123033286

参考2:https://blog.csdn.net/weixin_49223002/article/details/120509776

2、安装torch和cudatoolkit

首先创建一个Conda环境,名字为graspness,python版本为3.8

然后进行graspness环境

  1. conda create -n graspness python=3.8
  2. conda activate graspness

这里需要安装pytorch1.8.2,cudatoolkit=11.1

conda install pytorch torchvision torchaudio cudatoolkit=11.1 -c pytorch-lts -c nvidia

pytorch1.8.2官网地址:https://pytorch.org/get-started/previous-versions/ 

3、安装Graspness相关依赖库

下载graspness代码

  1. git clone https://github.com/rhett-chen/graspness_implementation.git
  2. cd graspnet-graspness

编辑 requirements.txt,注释torch和MinkowskiEngine

  1. # pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
  2. # torch>=1.8
  3. tensorboard==2.3
  4. numpy==1.23.5
  5. scipy
  6. open3d>=0.8
  7. Pillow
  8. tqdm
  9. # MinkowskiEngine==0.5.4

开始安装Graspness相关依赖库

pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

4、安装MinkowskiEngine

在安装MinkowskiEngine之前,需要先安装相关的依赖

pip install ninja  -i https://pypi.tuna.tsinghua.edu.cn/simple
conda install openblas-devel -c anaconda

然后本地安装的流程:

  1. export CUDA_HOME=/usr/local/cuda-11.1 # 指定CUDA_HOME为cuda-11.1
  2. export MAX_JOBS=2 # 降低占用CPU的核心数目,避免卡死(可选)
  3. git clone https://github.com/NVIDIA/MinkowskiEngine.git
  4. cd MinkowskiEngine
  5. python setup.py install --blas_include_dirs=${CONDA_PREFIX}/include --blas=openblas

等待安装完成

5、安装pointnet2和knn

这些两个的安装需要CUDA编译的,依赖于前面的export CUDA_HOME=/usr/local/cuda-11.1

首先来到graspnet-graspness工程中,安装pointnet2

  1. cd pointnet2
  2. python setup.py install

再安装knn

  1. cd knn
  2. python setup.py install

6、安装graspnetAPI 

这里安装的流程如下,逐条命令执行

  1. git clone https://github.com/graspnet/graspnetAPI.git
  2. cd graspnetAPI
  3. pip install . -i https://pypi.tuna.tsinghua.edu.cn/simple

成功安装后,需要再安装numpy==1.23.5

pip install numpy==1.23.5 -i https://pypi.tuna.tsinghua.edu.cn/simple

到这里安装完成啦~

7、模型推理——抓取点估计

跑一下模型推理的demo,看看可视化的效果:

2024.12.17 更新~

这里分享一下模型推理和可视化的代码

  1. import os
  2. import sys
  3. import numpy as np
  4. import argparse
  5. from PIL import Image
  6. import time
  7. import scipy.io as scio
  8. import torch
  9. import open3d as o3d
  10. from graspnetAPI.graspnet_eval import GraspGroup
  11. ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
  12. sys.path.append(ROOT_DIR)
  13. sys.path.append(os.path.join(ROOT_DIR, 'utils'))
  14. from models.graspnet import GraspNet, pred_decode
  15. from dataset.graspnet_dataset import minkowski_collate_fn
  16. from collision_detector import ModelFreeCollisionDetector
  17. from data_utils import CameraInfo, create_point_cloud_from_depth_image, get_workspace_mask
  18. # 参数解析器
  19. parser = argparse.ArgumentParser()
  20. parser.add_argument('--dataset_root', default='/home/lgp/2024_project/datasets/test_seen/', help='数据集根目录路径')
  21. parser.add_argument('--checkpoint_path', default='logs/log_kn/minkuresunet_kinect.tar', help='模型权重文件路径')
  22. parser.add_argument('--dump_dir', help='输出结果保存目录', default='logs/infer/')
  23. parser.add_argument('--seed_feat_dim', default=512, type=int, help='每个点的特征维度')
  24. parser.add_argument('--camera', default='kinect', help='摄像头类型 [realsense/kinect]')
  25. parser.add_argument('--num_point', type=int, default=50000, help='点云采样点数 [默认: 15000]')
  26. parser.add_argument('--batch_size', type=int, default=1, help='推理时的批大小 [默认: 1]')
  27. parser.add_argument('--voxel_size', type=float, default=0.005, help='稀疏卷积的体素大小[默认: 0.005]')
  28. parser.add_argument('--collision_thresh', type=float, default=0.06,help='碰撞检测阈值 [默认: 0.01], -1表示不进行碰撞检测')
  29. parser.add_argument('--voxel_size_cd', type=float, default=0.01, help='碰撞检测时体素大小[默认: 0.01]')
  30. parser.add_argument('--infer', action='store_true', default=True, help='是否进行推理')
  31. parser.add_argument('--vis', action='store_true', default=True, help='是否进行可视化')
  32. parser.add_argument('--scene', type=str, default='0102', help='场景ID')
  33. parser.add_argument('--index', type=str, default='0000', help='深度图索引')
  34. cfgs = parser.parse_args()
  35. # 如果输出目录不存在则创建
  36. if not os.path.exists(cfgs.dump_dir):
  37. os.mkdir(cfgs.dump_dir)
  38. def data_process():
  39. # 根据用户输入构造场景ID和索引
  40. root = cfgs.dataset_root
  41. camera_type = cfgs.camera
  42. depth_path = os.path.join(root, 'scenes', scene_id, camera_type, 'depth', index + '.png')
  43. seg_path = os.path.join(root, 'scenes', scene_id, camera_type, 'label', index + '.png')
  44. meta_path = os.path.join(root, 'scenes', scene_id, camera_type, 'meta', index + '.mat')
  45. # 新增:RGB图像路径
  46. rgb_path = os.path.join(root, 'scenes', scene_id, camera_type, 'rgb', index + '.png')
  47. # 加载深度图、语义分割图和RGB图像
  48. depth = np.array(Image.open(depth_path))
  49. seg = np.array(Image.open(seg_path))
  50. rgb = np.array(Image.open(rgb_path)) # 形状通常为(H, W, 3)
  51. # 加载相机内参和深度因子
  52. meta = scio.loadmat(meta_path)
  53. intrinsic = meta['intrinsic_matrix']
  54. factor_depth = meta['factor_depth']
  55. # 构造相机参数对象
  56. camera = CameraInfo(1280.0, 720.0, intrinsic[0][0], intrinsic[1][1], intrinsic[0][2], intrinsic[1][2],factor_depth)
  57. # 利用深度图生成点云 (H,W,3) 并保留组织结构
  58. cloud = create_point_cloud_from_depth_image(depth, camera, organized=True)
  59. # 创建有效深度掩码
  60. depth_mask = (depth > 0)
  61. # 加载相机位姿和对齐矩阵,用于获取工作空间mask
  62. camera_poses = np.load(os.path.join(root, 'scenes', scene_id, camera_type, 'camera_poses.npy'))
  63. align_mat = np.load(os.path.join(root, 'scenes', scene_id, camera_type, 'cam0_wrt_table.npy'))
  64. trans = np.dot(align_mat, camera_poses[int(index)])
  65. workspace_mask = get_workspace_mask(cloud, seg, trans=trans, organized=True, outlier=0.02)
  66. # 最终有效点的mask
  67. mask = (depth_mask & workspace_mask)
  68. # 根据mask过滤点云和对应的RGB颜色
  69. cloud_masked = cloud[mask] # (N,3)
  70. rgb_masked = rgb[mask] # (N,3)
  71. # 随机下采样点云至指定数量
  72. if len(cloud_masked) >= cfgs.num_point:
  73. idxs = np.random.choice(len(cloud_masked), cfgs.num_point, replace=False)
  74. else:
  75. # 如果点不够则有放回采样
  76. idxs1 = np.arange(len(cloud_masked))
  77. idxs2 = np.random.choice(len(cloud_masked), cfgs.num_point - len(cloud_masked), replace=True)
  78. idxs = np.concatenate([idxs1, idxs2], axis=0)
  79. cloud_sampled = cloud_masked[idxs] # (num_point, 3)
  80. rgb_sampled = rgb_masked[idxs] # (num_point, 3)
  81. # 返回包含点云、坐标、特征和颜色的字典
  82. ret_dict = {
  83. 'point_clouds': cloud_sampled.astype(np.float32),
  84. 'coors': (cloud_sampled / cfgs.voxel_size).astype(np.float32),
  85. 'feats': np.ones_like(cloud_sampled).astype(np.float32),
  86. 'colors': (rgb_sampled / 255.0).astype(np.float32) # 将RGB归一化到[0,1]
  87. }
  88. return ret_dict
  89. def my_worker_init_fn(worker_id):
  90. # 初始化worker随机种子(如果需要)
  91. np.random.seed(np.random.get_state()[1][0] + worker_id)
  92. pass
  93. def inference(data_input):
  94. # 将数据打包成Minkowski兼容格式
  95. batch_data = minkowski_collate_fn([data_input])
  96. # 实例化GraspNet模型
  97. net = GraspNet(seed_feat_dim=cfgs.seed_feat_dim, is_training=False)
  98. # 设置设备(GPU优先)
  99. device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
  100. net.to(device)
  101. # 加载模型权重
  102. checkpoint = torch.load(cfgs.checkpoint_path)
  103. net.load_state_dict(checkpoint['model_state_dict'])
  104. start_epoch = checkpoint['epoch']
  105. print("-> loaded checkpoint %s (epoch: %d)" % (cfgs.checkpoint_path, start_epoch))
  106. net.eval()
  107. tic = time.time()
  108. # 将batch数据移到GPU(若可用)
  109. for key in batch_data:
  110. if 'list' in key:
  111. for i in range(len(batch_data[key])):
  112. for j in range(len(batch_data[key][i])):
  113. batch_data[key][i][j] = batch_data[key][i][j].to(device)
  114. else:
  115. batch_data[key] = batch_data[key].to(device)
  116. # 前向推理
  117. with torch.no_grad():
  118. end_points = net(batch_data)
  119. grasp_preds = pred_decode(end_points)
  120. preds = grasp_preds[0].detach().cpu().numpy()
  121. gg = GraspGroup(preds)
  122. # 若设置了碰撞检测阈值则进行碰撞检测
  123. if cfgs.collision_thresh > 0:
  124. cloud = data_input['point_clouds']
  125. mfcdetector = ModelFreeCollisionDetector(cloud, voxel_size=cfgs.voxel_size_cd)
  126. collision_mask = mfcdetector.detect(gg, approach_dist=0.05, collision_thresh=cfgs.collision_thresh)
  127. gg = gg[~collision_mask]
  128. # 保存抓取结果
  129. save_dir = os.path.join(cfgs.dump_dir, scene_id, cfgs.camera)
  130. save_path = os.path.join(save_dir, cfgs.index + '.npy')
  131. if not os.path.exists(save_dir):
  132. os.makedirs(save_dir)
  133. gg.save_npy(save_path)
  134. toc = time.time()
  135. print('inference time: %fs' % (toc - tic))
  136. if __name__ == '__main__':
  137. # 根据参数构造scene_id和index
  138. scene_id = 'scene_' + cfgs.scene
  139. index = cfgs.index
  140. data_dict = data_process()
  141. # 若需要推理则调用inference函数
  142. if cfgs.infer:
  143. inference(data_dict)
  144. # 若需要可视化(彩色)
  145. if cfgs.vis:
  146. pc = data_dict['point_clouds']
  147. colors = data_dict['colors'] # 获取采样后点的颜色信息
  148. gg = np.load(os.path.join(cfgs.dump_dir, scene_id, cfgs.camera, cfgs.index + '.npy'))
  149. gg = GraspGroup(gg)
  150. gg = gg.nms() # 非极大值抑制去重
  151. gg = gg.sort_by_score() # 按置信度排序
  152. if gg.__len__() > 30:
  153. gg = gg[:30]
  154. grippers = gg.to_open3d_geometry_list()
  155. # 创建彩色点云对象
  156. cloud = o3d.geometry.PointCloud()
  157. cloud.points = o3d.utility.Vector3dVector(pc.astype(np.float32))
  158. cloud.colors = o3d.utility.Vector3dVector(colors)
  159. # 创建Open3D可视化窗口
  160. vis = o3d.visualization.Visualizer()
  161. vis.create_window(visible=True) # 若不需显示窗口可设False
  162. vis.add_geometry(cloud)
  163. for g in grippers:
  164. vis.add_geometry(g)
  165. # 刷新渲染器和事件循环,确保图像更新
  166. vis.update_renderer()
  167. vis.poll_events()
  168. vis.run() # 若想交互查看可保留run()
  169. # 截图保存
  170. screenshot_path = os.path.join(cfgs.dump_dir, scene_id, cfgs.camera, cfgs.index + '_vis-RGB.png')
  171. vis.capture_screen_image(screenshot_path)
  172. # 销毁窗口
  173. vis.destroy_window()
  174. print("Screenshot saved at:", screenshot_path)
  175. # 若需要可视化(纯点云版本)
  176. if cfgs.vis:
  177. pc = data_dict['point_clouds']
  178. gg = np.load(os.path.join(cfgs.dump_dir, scene_id, cfgs.camera, cfgs.index + '.npy'))
  179. gg = GraspGroup(gg)
  180. gg = gg.nms()
  181. gg = gg.sort_by_score()
  182. if gg.__len__() > 30:
  183. gg = gg[:30]
  184. grippers = gg.to_open3d_geometry_list()
  185. cloud = o3d.geometry.PointCloud()
  186. cloud.points = o3d.utility.Vector3dVector(pc.astype(np.float32))
  187. # 创建可视化窗口(纯点云)
  188. vis = o3d.visualization.Visualizer()
  189. vis.create_window(visible=True)
  190. vis.add_geometry(cloud)
  191. for g in grippers:
  192. vis.add_geometry(g)
  193. vis.update_renderer()
  194. vis.poll_events()
  195. vis.run()
  196. # 保存截图
  197. screenshot_path = os.path.join(cfgs.dump_dir, scene_id, cfgs.camera, cfgs.index + '_vis.png')
  198. vis.capture_screen_image(screenshot_path)
  199. vis.destroy_window()
  200. print("Screenshot saved at:", screenshot_path)

看看检测效果,会输出彩色+点云的抓取效果:

然后输出纯三维点云的抓取效果:

看看其他示例,首先看看输出彩色+点云的抓取效果:

然后输出纯三维点云的抓取效果:

GraspNess的原理分析,参考我这篇文章

【机器人】Graspness 端到端 抓取点估计 | 论文解读-CSDN博客

分享完成~

注:本文转载自blog.csdn.net的一颗小树x的文章"https://blog.csdn.net/qq_41204464/article/details/144472778"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top