本文小編為大家詳細(xì)介紹“如何用Python實(shí)現(xiàn)點(diǎn)云的地面檢測”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“如何用Python實(shí)現(xiàn)點(diǎn)云的地面檢測”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識(shí)吧。
發(fā)展壯大離不開廣大客戶長期以來的信賴與支持,我們將始終秉承“誠信為本、服務(wù)至上”的服務(wù)理念,堅(jiān)持“二合一”的優(yōu)良服務(wù)模式,真誠服務(wù)每家企業(yè),認(rèn)真做好每個(gè)細(xì)節(jié),不斷完善自我,成就企業(yè),實(shí)現(xiàn)共贏。行業(yè)涉及砂巖浮雕等,在網(wǎng)站建設(shè)、營銷型網(wǎng)站建設(shè)、WAP手機(jī)網(wǎng)站、VI設(shè)計(jì)、軟件開發(fā)等項(xiàng)目上具有豐富的設(shè)計(jì)經(jīng)驗(yàn)。
在開始之前,了解計(jì)算機(jī)視覺中的傳統(tǒng)坐標(biāo)系是很重要的。其次是Open3D和Microsoft Kinect傳感器。在計(jì)算機(jī)視覺中,圖像用獨(dú)立的2D坐標(biāo)系表示,其中x軸從左向右指向,y軸是上下指向。對于相機(jī),3D坐標(biāo)系原點(diǎn)位于相機(jī)的焦點(diǎn)處,x軸指向右,y軸指向下,z軸指向前。
計(jì)算機(jī)視覺坐標(biāo)系
我們首先導(dǎo)入所需的Python庫:
import numpy as np import open3d as o3d
為了更好地理解,讓我們從 PLY 文件中導(dǎo)入點(diǎn)云,使用 Open3D 創(chuàng)建默認(rèn)的 3D 坐標(biāo)系并顯示它們:
# 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)
以坐標(biāo)系原點(diǎn)顯示的點(diǎn)云
藍(lán)色箭頭是 Z 軸,紅色箭頭是 X 軸,綠色箭頭是 Y 軸??梢钥吹近c(diǎn)云在與Open3D坐標(biāo)系相同的坐標(biāo)系中表示。現(xiàn)在,讓我們獲取具有每個(gè)軸的最小值和最大值的點(diǎn):
# 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])
我們可以打印它們,但為了更好的可視化,我們在每個(gè)點(diǎn)位置創(chuàng)建一個(gè)球體。默認(rèn)情況下,Open3D在原點(diǎn)位置創(chuàng)建3D幾何圖形:
要將球體移動(dòng)到給定位置,需要進(jìn)行平移變換。在下面的示例中,球體以向量 [1,1,1] 平移:
讓我們回到我們的示例,為每個(gè)球體分配一個(gè)顏色。對于每個(gè)位置,我們創(chuàng)建一個(gè)球體并將其平移到該位置。然后,我們分配正確的顏色,最后我們將它添加到顯示。
# 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)
實(shí)際上,y軸代表了點(diǎn)的高度:在現(xiàn)實(shí)世界中,最高的球是黃色的球,最低的球是綠色的球。但是,由于y軸向下,黃色球體的值最小,綠色球體的值最大。
另一個(gè)有趣的球體是原點(diǎn)上的青色球體。正如我們在上一篇教程中提到的,深度值為0的像素是噪聲點(diǎn),因此位于原點(diǎn)的點(diǎn)是從這些噪聲像素計(jì)算出來的點(diǎn)(當(dāng)z=0時(shí),則x=0和y=0)。
現(xiàn)在我們已經(jīng)展示了一些重要的點(diǎn),如何進(jìn)行地面檢測呢?在前面的例子中,綠色球體位于地面上。確切地說,它的中心對應(yīng)于沿y軸的最高點(diǎn)是一個(gè)地面點(diǎn)。假設(shè)為了地面檢測,我們將所有具有y_max的點(diǎn)的顏色都更改為綠
如果顯示點(diǎn)云,您會(huì)注意到并非所有的地面點(diǎn)都是綠色的。事實(shí)上,只有一個(gè)與前面綠色球體的中心相對應(yīng)的點(diǎn)是綠色的。這是由于深度相機(jī)的精度和噪聲造成的。
為了克服這個(gè)限制,我們需要添加一個(gè)閾值,以便將y坐標(biāo)為[y_max-threshold, y_max]的點(diǎn)都視為地面點(diǎn)。為此,在得到y(tǒng)_max后,我們檢查每個(gè)點(diǎn)的y坐標(biāo)是否在該區(qū)間內(nèi),然后將其顏色設(shè)置為綠色。最后更新點(diǎn)云的顏色屬性并顯示結(jié)果。
# 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])
在本例中,我們只將代表地面的點(diǎn)涂成綠色。在現(xiàn)實(shí)世界的應(yīng)用中,地面被提取來定義可行走的區(qū)域,如機(jī)器人或視覺障礙系統(tǒng),或在其上放置物體,如室內(nèi)設(shè)計(jì)系統(tǒng)。它也可以被刪除,所以剩下的點(diǎn)可以被分割或分類,就像在場景理解和目標(biāo)檢測系統(tǒng)一樣。
我們知道點(diǎn)云定義為一組3D點(diǎn)。集合是一種無序結(jié)構(gòu),因此集合所表示的點(diǎn)云稱為無組織點(diǎn)云。與RGB矩陣類似,有組織的點(diǎn)云是一個(gè)2D矩陣,有3個(gè)通道表示點(diǎn)的x、y和z坐標(biāo)。矩陣結(jié)構(gòu)提供了相鄰點(diǎn)之間的關(guān)系,從而降低了一些算法的時(shí)間復(fù)雜度,如最近鄰算法。
舉個(gè)例子,我們正在寫一篇研究論文,我們想用圖的形式展示我們的檢測算法的結(jié)果。我們既可以截取點(diǎn)云的截圖,也可以將結(jié)果顯示在深度圖像上,如下圖所示。在我看來,第二個(gè)選擇是最好的。在這種情況下,需要一個(gè)有組織的點(diǎn)云來保存深度像素的位置。
左:3D 可視化的屏幕截圖 右:深度圖像的結(jié)果
讓我們從之前的深度圖像創(chuàng)建一個(gè)有組織的點(diǎn)云。我們首先導(dǎo)入相機(jī)參數(shù)。我們還導(dǎo)入深度圖像并將其轉(zhuǎn)換為3通道灰度圖像,以便我們可以將地面像素設(shè)置為綠色:
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)
要計(jì)算一個(gè)有組織的點(diǎn)云,我們使用與上一篇教程相同的方法(Python:基于 RGB-D 圖像的點(diǎn)云計(jì)算)。我們沒有將深度圖像扁平化,而是將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))
如果你打印出創(chuàng)建的點(diǎn)云的形狀,你可以看到它是一個(gè)有3個(gè)通道的矩陣(480,640,3)。如果你覺得這個(gè)代碼很難理解,請回到之前的教程(Python:基于 RGB-D 圖像的點(diǎn)云計(jì)算)。
類似地,我們像上面那樣檢測地面,但不是更新點(diǎn)的顏色并顯示點(diǎn)云,而是更新灰度圖像的像素并顯示它:
# 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()
讀到這里,這篇“如何用Python實(shí)現(xiàn)點(diǎn)云的地面檢測”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。