基于D435i的点云重建

2023-05-16

Task: 采用D435i采集深度图和RGB图像,进行点云重建和聚类。

1)解析Bag数据:

import os
import cv2
import numpy as np
import rosbag
from cv_bridge import CvBridge
import sensor_msgs.point_cloud2 as pc2
from sensor_msgs.msg import PointCloud2

import pcl
from pcl import pcl_visualization
import pyrealsense2 as rs

import numpy as np
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from skimage.segmentation import chan_vese
import time
import copy


if __name__ == "__main__":   
 visual = pcl_visualization.CloudViewing()
    pc = rs.pointcloud()
    points = rs.points()

    bag = rosbag.Bag(file_path, "r")
    bag_data = bag.read_messages()
    info = bag.get_type_and_topic_info()
    print(info)

    bridge = CvBridge()
    depth = None; points_tp = None; cv_img10 = None

    cap = cv2.VideoWriter(video_output, cv2.VideoWriter_fourcc(*'MP4V'), 20.0, (1280*2+3, 720))
    nn = 0
    for topic, msg, t in bag_data:
        print(topic)
        if topic == "/cam_1/aligned_depth_to_color/image_raw/compressed":
            depth = bridge.compressed_imgmsg_to_cv2(msg)
            show_img(depth, "Depth Image")
        elif topic == "/cam_1/color/image_raw/compressed":
            cv_img = bridge.compressed_imgmsg_to_cv2(msg)
            show_img(cv_img, "Cam1")
        elif topic == "/cam_2/aligned_depth_to_color/image_raw/compressed":
            depth_10 = bridge.compressed_imgmsg_to_cv2(msg)
        elif topic == "/cam_2/color/image_raw/compressed":
            cv_img10 = bridge.compressed_imgmsg_to_cv2(msg)
            show_img(cv_img10, "Cam2")
            seg_color, add_image = visual_pcl(visual, depth_10, cv_img10)
            save_seg_video(cap, cv_img10, add_image)
            # if nn == 2499:    # 保存某一帧的数据和结果
            #     seg, seg_color, add_image = visual_pcl(visual, depth_10, cv_img10)
            # #     cv2.imwrite("./save_data/test_rgb.png", cv_img10)
            # #     cv2.imwrite("./save_data/test_depth.png", depth_10)
            # #     xyz_sand = depth2xyz(depth_10, depth_camera_metrix)
            # #     xyz_sand = xyz_sand.reshape(-1, 3)
            # #     with open("./save_data/points.txt", "w") as f:
            # #         for i in range(len(xyz_sand)):
            # #             strings = str(xyz_sand[i][0]) + "," + str(xyz_sand[i][1]) + "," + str(xyz_sand[i][2]) +"\n"
            # #             f.write(strings)
        elif topic == "/cam_3/color/image_raw/compressed":
            cv_img = bridge.compressed_imgmsg_to_cv2(msg)
            show_img(cv_img, "Cam3")
        nn = nn + 1
        print(nn)

    cap.release()
    print("end")

2)分割图像:

# 图像显示
def show_img(img, window_name):
    if SHOW_IMAGE:
        cv2.imshow(window_name, img)
        cv2.waitKey(3)

# 寻找最大连通域
def find_max_region(mask_sel):
    contours, hierarchy = cv2.findContours(mask_sel,cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
 
    #找到最大区域并填充 
    area = []
 
    for j in range(len(contours)):
        area.append(cv2.contourArea(contours[j]))
 
    max_idx = np.argmax(area)
  
    for k in range(len(contours)):
    
        if k != max_idx:
            cv2.fillPoly(mask_sel, [contours[k]], 0)
        # elif k == max_idx:
        #     cv2.fillPoly(mask_sel, [contours[k]], 255)
    return mask_sel


# 填充孔洞
def FillHole(img):

    # 复制 im_in 图像
    im_floodfill = img.copy()
    
    # Mask 用于 floodFill,官方要求长宽+2
    h, w = img.shape[:2]
    mask = np.zeros((h+2, w+2), np.uint8)
    
    # floodFill函数中的seedPoint必须是背景
    isbreak = False
    seedPoint = None
    for i in range(im_floodfill.shape[0] - 2):
        for j in range(im_floodfill.shape[1] - 2):
            if(im_floodfill[i][j]==0):
                seedPoint=(i,j)
                isbreak = True
                break
        if(isbreak):
            break
    # 得到im_floodfill
    try:
        if seedPoint is not None:
            cv2.floodFill(im_floodfill, mask, seedPoint, 255)

            # 得到im_floodfill的逆im_floodfill_inv
            im_floodfill_inv = cv2.bitwise_not(im_floodfill)
            # 把im_in、im_floodfill_inv这两幅图像结合起来得到前景
            im_out = img | im_floodfill_inv
            return im_out
        else:
            return img
    except:
        return img



def segmentation_rgb(img):
    origin_img = img
    show_img(origin_img, "Origin R image")

    img = cv2.GaussianBlur(img, (5, 5), 1)
    h, w, c = img.shape
    ret3, segr = cv2.threshold(img[:, :, 2], 0, 255, cv2.THRESH_OTSU)

    show_img(segr, "Origin Seg R")

    kernel = np.ones((5, 5), np.uint8)
    segr = cv2.morphologyEx(segr, cv2.MORPH_OPEN, kernel, iterations=2)
    show_img(segr, "Seg R Open Operation")

    segr = cv2.dilate(segr, kernel, iterations=3)
    show_img(segr, "Seg R Dilate Operation")

    segr = FillHole(segr)

    show_img(segr, "Seg R Fill Hole")

    img[:, :, 2][segr > 0] = 0

    # 再次分割
    ret3, segrnew = cv2.threshold(img[:, :, 2], 0, 255, cv2.THRESH_OTSU)
    segrnew[segr == 255] = 0

    show_img(segrnew, "Re-seg R SEG")

    show_img(img[:, :, 0], "B")
    show_img(img[:, :, 2], "R")
    show_img(img[:, :, 1], "G")

    segr = find_max_region(segrnew)
    mm = segr[190:, :]
    tp = FillHole(mm)
    segr[190:, :] = tp
    show_img(segr, "Re R SEG - find max region and fill hole")
    add_image = show_mask_on_image(origin_img, segr)

    dp_car = copy.copy(depth)
    dp_sand = copy.copy(depth)
    dp_car[segr == 255] = 0
    dp_sand[segr == 0] = 0
    show_img(dp_car, "Depth - Car")
    show_img(dp_sand, "Depth - Sand")

    return segr, add_image

3)深度图计算点云图:

# 由深度图,计算点云图
def depth2xyz(depth_map,depth_cam_matrix,flatten=False,depth_scale=1000):
    fx,fy = depth_cam_matrix[0,0],depth_cam_matrix[1,1]
    cx,cy = depth_cam_matrix[0,2],depth_cam_matrix[1,2]
    h,w=np.mgrid[0:depth_map.shape[0],0:depth_map.shape[1]]
    z=depth_map/depth_scale
    x=(w-cx)*z/fx
    y=(h-cy)*z/fy
    xyz=np.dstack((x,y,z)) if flatten==False else np.dstack((x,y,z)).reshape(-1,3)
    return xyz

4)点云重建和可视化:

def visual_pcl(visual, depth, color):
    t1 = time.time()
    seg_color, add_image = segmentation_rgb(color)
    print("Segmentation time: ", time.time() - t1, "s")

    if GET_POINT:
        seg_color[seg_color == 0] = 20
        seg_color = cv2.cvtColor(seg_color, cv2.COLOR_GRAY2BGR)

        depth_sand = depth

        t2 = time.time()
        xyz_sand = depth2xyz(depth_sand, depth_camera_metrix)
        print("Depth to point cloud time: ", time.time() - t2, "s")
        xyz_sand = xyz_sand.reshape(-1, 3)

        seg_color = seg_color.reshape(-1,3)
        color = color.reshape(-1,3)
        # seg_color[seg_color > 0] = 255    # 聚类前结果,修改颜色值即可

        # kmeans(xyz_sand, xyz_vehicle)     # 采用kmeans方法进行聚类

        cloud = pcl.PointCloud_PointXYZRGB()
        temp = np.zeros((len(xyz_sand), 4), np.float32)
        length = len(xyz_sand)
        for i in range(length):
            temp[i][0] = xyz_sand[i][0] * 1000.0
            temp[i][1] = xyz_sand[i][1] * 1000.0
            temp[i][2] = xyz_sand[i][2] * 1000.0
            # temp[i][3] = 65536.0 * color[i][2] + 256.0*color[i][1] + color[i][0]      # 用原图像的颜色信息渲染点云
            temp[i][3] = 65536.0 * seg_color[i][2] + 256.0*seg_color[i][1] + seg_color[i][0]

        cloud.from_array(temp)
        visual.ShowColorCloud(cloud, b"color")

    return seg_color, add_image

结果:

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于D435i的点云重建 的相关文章

随机推荐

  • XShell过期需要采购解决办法

    有天Xshell更新完再打开 xff0c 提示我去采购 xff0c 当然采购得花钱 xff0c 所以下面方法是解决这一问题 1 跳到官网 https www netsarang com download free license html
  • 【SMT32CubeMx安装详解】

    SMT32CubeMx安装详解 文章目录 SMT32CubeMx安装详解 前言一 准备工作二 CubeMax安装三 工程参数配置总结 前言 记录CubeMax软件安装和相关工程配置的简单操作 一 准备工作 在我们进行软件安装之前首先将我们需
  • AirSim无人机仿真平台(windows)

    1 环境 xff1a UE4 26 43 AirSim 43 VS2019 2 安装步骤 xff1a 1 xff09 先下载Epic Games安装启动器 xff0c 然后再安装UE4 26 xff1b 2 xff09 安装VS2019社区
  • ubuntu18在docker下运行kalibr

    一些命令 docker images sudo docker run it kalibr latest sudo docker run it v local path docker path respository bin bash sud
  • 机器人避障规划算法之VFH系列算法研究现状

    机器人路径规划算法可以分为全局路径规划与局部路径规划 xff0c 全局规划算法一般需要地图信息作为先验知识 xff0c 而局部规划算法利用传感器探测环境信息避开障碍物 常用的全局算法算法有可视图法 xff0c 栅格地图法 xff0c 智能算
  • Windows配置ArUco

    windows10 vs2019 opencv3 4 6 注意 xff0c 一定要选择与opencv版本一样的opencv contrib 进行编译 xff0c 否则将会出现错误 xff0c 有很多的工程不能编译通过 xff0c 不能产生相
  • ArUco估计位姿原理

    ArUco使用 PnP OpenCV aruco 校准相机 Camera Calibration Demo 使用opencv的aruco库进行位姿估计 include lt opencv2 core core hpp gt include
  • 传递函数极点与微分方程的解

    如何解微分方程 setting y 61 e rx xff0c 点睛之笔
  • MPC控制

    基于状态空间模型的控制 模型预测控制 xff08 MPC xff09 简介 对基于状态空间模型的控制理解得很到位 在这里我重点讲解一下状态空间 模型 那么什么是状态 xff1f 输出是不是也是状态的一种 xff1f 对的 xff0c 输出也
  • @卡尔曼滤波理解

    Kalman Filter For Dummies 翻译 如何用卡尔曼滤波算法求解电池SOC xff08 基础篇 xff09 转载留存 卡尔曼滤波算法详细推导 这一篇对预备知识的介绍还是很好的 xff0c 过程与原理讲解也很到位 xff0c
  • 全景避障、VIO

    VINS Mono代码分析与总结 完整版 单目与IMU的融合可以有效解决单目尺度不可观测的问题 鱼眼摄像头SLAM xff1a PAN SLAM 全景相机SLAM 原论文 xff1a Panoramic SLAM from a multip
  • CAN总线-ACK应答机制分析

    1 xff1a 应答场定义 应答场长度为 2 个位 xff0c 包含应答间隙 xff08 ACK SLOT xff09 和应答界定符 xff08 ACK DELIMITER xff09 在应答场里 xff0c 发送站发送两个 隐性 位 当接
  • 树莓派4b 引脚图

    树莓派 4B 详细资料
  • 控制~线性系统~的能控性和能观性

    现控笔记 xff08 四 xff09 xff1a 能控性和能观性 能控性 xff1a 是控制作用u t 支配系统的状态向量x t 的能力 xff1b 回答u t 能否使x t 作任意转移的问题 能观性 xff1a 是系统的输出y t 反映系
  • 创建功能包

    创建功能包 xff1a catkin create pkg 在Amos WS src路径下 xff0c 打开控制台输入catkin create pkg my package std msgs rospy roscpp 创建一个名为my p
  • SLAM算法

    一 概述 Simultaneous Localization and Mapping SLAM 原本是Robotics领域用来做机器人定位的 xff0c 最早的SLAM算法其实是没有用视觉camera的 xff08 Robotics领域一般
  • 激光雷达入门

    转载自 xff1a https zhuanlan zhihu com p 33792450 前言 上一次的分享里 xff0c 我介绍了一个重要的感知传感器 摄像机 摄像机作为视觉传感器 xff0c 能为无人车提供丰富的感知信息 但是由于本身
  • 【超详细】韦东山:史上最全嵌入式Linux学习路线图

    我是1999年上的大学 xff0c 物理专业 在大一时 xff0c 我们班里普遍弥漫着对未来的不安 xff0c 不知道学习了物理后出去能做什么 你当下的经历 当下的学习 xff0c 在未来的一天肯定会影响到你 毕业后我们也各自找到了自己的职
  • ArUco码辅助定位——计算机视觉

    使用USB网络摄像头和ROS跟踪ArUco Markers
  • 基于D435i的点云重建

    Task 采用D435i采集深度图和RGB图像 xff0c 进行点云重建和聚类 1 xff09 解析Bag数据 xff1a import os import cv2 import numpy as np import rosbag from