利用 Python 實現點雲的地面檢測

王林
發布: 2023-05-09 17:28:08
轉載
1638 人瀏覽過

1. 電腦視覺座標系統

在開始之前,了解電腦視覺中的傳統座標係是很重要的。其次是Open3D和Microsoft Kinect感測器。在電腦視覺中,影像以獨立的2D座標系表示,其中x軸從左向右指向,y軸是上下指向。對於相機,3D座標係原點位於相機的焦點處,x軸指向右,y軸指向下,z軸指向前。

了解点云:使用 Python 实现地面检测

電腦視覺座標系

我們先匯入所需的Python函式庫:

import numpy as np
import open3d as o3d
登入後複製

為了更好地理解,讓我們從PLY 檔案中匯入點雲,使用Open3D 建立預設的3D 座標系並顯示它們:

# Read point cloud:
pcd = o3d.io.read_point_cloud("data/depth_2_pcd.ply")
# Create a 3D coordinate system:
origin = o3d.geometry.TriangleMesh.create_coordinate_frame(size=0.5)
# geometries to draw:
geometries = [pcd, origin]
# Visualize:
o3d.visualization.draw_geometries(geometries)
登入後複製

了解点云:使用 Python 实现地面检测

#以座標系原點顯示的點雲

藍色箭頭是Z 軸,紅色箭頭是X 軸,綠色箭頭是Y 軸。可以看到點雲在與Open3D座標系相同的座標系中表示。現在,讓我們取得具有每個軸的最小值和最大值的點:

# Get max and min points of each axis x, y and z:
x_max = max(pcd.points, key=lambda x: x[0])
y_max = max(pcd.points, key=lambda x: x[1])
z_max = max(pcd.points, key=lambda x: x[2])
x_min = min(pcd.points, key=lambda x: x[0])
y_min = min(pcd.points, key=lambda x: x[1])
z_min = min(pcd.points, key=lambda x: x[2])
登入後複製

我們可以列印它們,但為了更好的視覺化,我們在每個點位置建立一個球體。預設情況下,Open3D在原點位置建立3D幾何圖形:

了解点云:使用 Python 实现地面检测

#要將球體移到給定位置,需要進行平移變換。在下面的範例中,球體以向量 [1,1,1] 平移:

了解点云:使用 Python 实现地面检测

讓我們回到我們的範例,為每個球體分配一個顏色。對於每個位置,我們建立一個球體並將其平移到該位置。然後,我們分配正確的顏色,最後我們將它添加到顯示。

# Colors:
RED = [1., 0., 0.]
GREEN = [0., 1., 0.]
BLUE = [0., 0., 1.]
YELLOW = [1., 1., 0.]
MAGENTA = [1., 0., 1.]
CYAN = [0., 1., 1.]


positions = [x_max, y_max, z_max, x_min, y_min, z_min]
colors = [RED, GREEN, BLUE, MAGENTA, YELLOW, CYAN]
for i in range(len(positions)):
 # Create a sphere mesh:
 sphere = o3d.geometry.TriangleMesh.create_sphere(radius=0.05)
 # move to the point position:
 sphere.translate(np.asarray(positions[i]))
 # add color:
 sphere.paint_uniform_color(np.asarray(colors[i]))
 # compute normals for vertices or faces:
 sphere.compute_vertex_normals()
 # add to geometry list to display later:
 geometries.append(sphere)


# Display:
o3d.visualization.draw_geometries(geometries)
登入後複製

了解点云:使用 Python 实现地面检测

實際上,y軸代表了點的高度:在現實世界中,最高的球是黃色的球,最低的球是綠色的球。但是,由於y軸向下,黃色球體的值最小,綠色球體的值最大。

另一個有趣的球體是原點上的青色球體。正如我們在上一篇教學中提到的,深度值為0的像素是雜訊點,因此位於原點的點是從這些雜訊像素計算出來的點(當z=0時,則x=0和y= 0)。

2.地面偵測

現在我們已經展示了一些重要的點,如何進行地面偵測呢?在前面的例子中,綠色球體位於地面上。確切地說,它的中心對應於沿著y軸的最高點是一個地面點。假設為了地面偵測,我們將所有具有y_max的點的顏色都變更為綠色

如果顯示點雲,您會注意到並非所有的地面點都是綠色的。事實上,只有一個與前面綠色球體的中心相對應的點是綠色的。這是由於深度相機的精度和雜訊造成的。

為了克服這個限制,我們需要加入一個閾值,以便將y座標為[y_max-threshold, y_max]的點都視為地面點。為此,在得到y_max後,我們檢查每個點的y座標是否在該區間內,然後將其顏色設為綠色。最後更新點雲的顏色屬性並顯示結果。

# Define a threshold:
THRESHOLD = 0.075


# Get the max value along the y-axis:
y_max = max(pcd.points, key=lambda x: x[1])[1]


# Get the original points color to be updated:
pcd_colors = np.asarray(pcd.colors)


# Number of points:
n_points = pcd_colors.shape[0]


# update color:
for i in range(n_points):
# if the current point is aground point:
if pcd.points[i][1] >= y_max - THRESHOLD:
pcd_colors[i] = GREEN# color it green


pcd.colors = o3d.utility.Vector3dVector(pcd_colors)


# Display:
o3d.visualization.draw_geometries([pcd, origin])
登入後複製

了解点云:使用 Python 实现地面检测

在本例中,我們只將代表地面的點塗成綠色。在現實世界的應用中,地面被提取來定義可行走的區域,如機器人或視覺障礙系統,或在其上放置物體,如室內設計系統。它也可以被刪除,所以剩下的點可以被分割或分類,就像在場景理解和目標偵測系統一樣。

3. 有組織的點雲

我們知道點雲定義為一組3D點。集合是一種無序結構,因此集合所表示的點雲稱為無組織點雲。與RGB矩陣類似,有組織的點雲是2D矩陣,有3個通道表示點的x、y和z座標。矩陣結構提供了相鄰點之間的關係,從而降低了一些演算法的時間複雜度,例如最近鄰演算法。

舉個例子,我們正在寫一篇研究論文,我們想用圖的形式來展示我們的偵測演算法的結果。我們既可以截取點雲的截圖,也可以將結果顯示在深度影像上,如下圖所示。在我看來,第二個選擇是最好的。在這種情況下,需要一個有組織的點雲來保存深度像素的位置。

了解点云:使用 Python 实现地面检测

左:3D 可视化的屏幕截图 右:深度图像的结果

让我们从之前的深度图像创建一个有组织的点云。我们首先导入相机参数。我们还导入深度图像并将其转换为3通道灰度图像,以便我们可以将地面像素设置为绿色:

import imageio.v3 as iio
import numpy as np
import matplotlib.pyplot as plt


# Camera parameters:
FX_DEPTH = 5.8262448167737955e+02
FY_DEPTH = 5.8269103270988637e+02
CX_DEPTH = 3.1304475870804731e+02
CY_DEPTH = 2.3844389626620386e+02


# Read depth image:
depth_image = iio.imread('../data/depth_2.png')
# Compute the grayscale image:
depth_grayscale = np.array(256 * depth_image / 0x0fff, dtype=np.uint8)
# Convert a grayscale image to a 3-channel image:
depth_grayscale = np.stack((depth_grayscale,) * 3, axis=-1)
登入後複製

要计算一个有组织的点云,我们使用与上一篇教程相同的方法(Python:基于 RGB-D 图像的点云计算)。我们没有将深度图像扁平化,而是将jj和ii重塑为与深度图像相同的形状,如下所示:

# get depth image resolution:
height, width = depth_image.shape
# compute indices and reshape it to have the same shape as the depth image:
jj = np.tile(range(width), height).reshape((height, width))
ii = np.repeat(range(height), width).reshape((height, width))
# Compute constants:
xx = (jj - CX_DEPTH) / FX_DEPTH
yy = (ii - CY_DEPTH) / FY_DEPTH
# compute organised point cloud:
organized_pcd = np.dstack((xx * depth_image, yy * depth_image, depth_image))
登入後複製

如果你打印出创建的点云的形状,你可以看到它是一个有3个通道的矩阵(480,640,3)。如果你觉得这个代码很难理解,请回到之前的教程(Python:基于 RGB-D 图像的点云计算)。

类似地,我们像上面那样检测地面,但不是更新点的颜色并显示点云,而是更新灰度图像的像素并显示它:

# Ground_detection:
THRESHOLD = 0.075 * 1000# Define a threshold
y_max = max(organized_pcd.reshape((height * width, 3)), key=lambda x: x[1])[
1]# Get the max value along the y-axis


# Set the ground pixels to green:
for i in range(height):
for j in range(width):
if organized_pcd[i][j][1] >= y_max - THRESHOLD:
depth_grayscale[i][j] = [0, 255, 0]# Update the depth image


# Display depth_grayscale:
plt.imshow(depth_grayscale)
plt.show()
登入後複製

4.结论

在本教程中,为了熟悉点云,我们引入了默认坐标系统,并实现了一个简单的地面检测算法。事实上,地面检测在某些应用(如导航)中是一项重要的任务,文献中已经提出了几种算法。实现算法简单;它认为最低点是地面。然而,它的限制是,深度相机必须与地面平行,这是大多数现实应用的情况不是这样的。


以上是利用 Python 實現點雲的地面檢測的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:51cto.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!