Open3d之互動式可視化
- 2021 年 2 月 9 日
- 筆記
本篇教程介紹了Open3D的可視化窗口的交互功能。
# -*- coding:utf-8 -*-
import copy
import numpy as np
import open3d as o3d
def demo_crop_geometry():
print("手動幾何裁剪演示")
print(
"1) 按兩次「Y」以將幾何體與Y軸的負方向對齊"
)
print("2) 按「K」鎖定螢幕並切換到選擇模式")
print("3) 拖動以選擇矩形,")
print(" 或者使用ctrl+左鍵單擊進行多邊形選擇")
print("4) 按「C」獲取選定的幾何圖形並保存")
print("5) 按「F」切換到自由視圖模式")
# 載入點雲
pcd = o3d.io.read_point_cloud("../../test_data/ICP/cloud_bin_0.pcd")
# 可視化幾何體供用戶交互
o3d.visualization.draw_geometries_with_editing([pcd])
def draw_registration_result(source, target, transformation):
"""繪製配准結果"""
source_temp = copy.deepcopy(source)
target_temp = copy.deepcopy(target)
source_temp.paint_uniform_color([1, 0.706, 0])
target_temp.paint_uniform_color([0, 0.651, 0.929])
source_temp.transform(transformation)
o3d.visualization.draw_geometries([source_temp, target_temp])
def pick_points(pcd):
print("")
print(
"1) 請使用至少選擇三個對應關係 [shift + 左擊]"
)
print(" 按 [shift + 右擊] 撤銷拾取的點")
print("2) 拾取點後,按「Q」關閉窗口")
vis = o3d.visualization.VisualizerWithEditing()
vis.create_window()
vis.add_geometry(pcd)
# 激活窗口。此函數將阻止當前執行緒,直到窗口關閉。
vis.run() # 等待用戶拾取點
vis.destroy_window()
print("")
return vis.get_picked_points()
def demo_manual_registration():
print("手動ICP演示")
# 載入點雲
source = o3d.io.read_point_cloud("../../test_data/ICP/cloud_bin_0.pcd")
target = o3d.io.read_point_cloud("../../test_data/ICP/cloud_bin_2.pcd")
print("手動對齊前兩點雲的可視化")
draw_registration_result(source, target, np.identity(4))
# 從兩點雲中拾取點並建立對應關係
picked_id_source = pick_points(source)
picked_id_target = pick_points(target)
assert (len(picked_id_source) >= 3 and len(picked_id_target) >= 3)
assert (len(picked_id_source) == len(picked_id_target))
corr = np.zeros((len(picked_id_source), 2))
corr[:, 0] = picked_id_source
corr[:, 1] = picked_id_target
# 利用對應關係估計粗變換
print("使用用戶給定的對應關係計算粗糙變換")
p2p = o3d.pipelines.registration.TransformationEstimationPointToPoint()
trans_init = p2p.compute_transformation(source, target,
o3d.utility.Vector2iVector(corr))
# 用於改善的點對點ICP
print("執行點對點ICP改善")
threshold = 0.03 # 3cm距離閾值
reg_p2p = o3d.pipelines.registration.registration_icp(
source, target, threshold, trans_init,
o3d.pipelines.registration.TransformationEstimationPointToPoint())
draw_registration_result(source, target, reg_p2p.transformation)
print("")
if __name__ == "__main__":
demo_crop_geometry()
demo_manual_registration()
此腳本執行了兩個用戶交互應用程式:demo_crop_geometry()
和demo_manual_registration()
。
裁剪幾何體
def demo_crop_geometry():
print("手動幾何裁剪演示")
print(
"1) 按兩次「Y」以將幾何體與Y軸的負方向對齊"
)
print("2) 按「K」鎖定螢幕並切換到選擇模式")
print("3) 拖動以選擇矩形,")
print(" 或者使用ctrl+左鍵單擊進行多邊形選擇")
print("4) 按「C」獲取選定的幾何圖形並保存")
print("5) 按「F」切換到自由視圖模式")
# 載入點雲
pcd = o3d.io.read_point_cloud("../../test_data/ICP/cloud_bin_0.pcd")
# 可視化幾何體供用戶交互
o3d.visualization.draw_geometries_with_editing([pcd])
這個函數簡單讀取了一個點雲數據然後調用了draw_geometries_with_editing
函數,該函數提供了頂點選擇和裁剪功能。
注意
Open3D有一個繼承Visualizer類的VisualizerWithEditing類。它提供了圖形用戶交互功能。同樣的例子在自定義可視化中,VisualizerWithEditing()是可以顯示的替換掉draw_geometries_with_editing([pcd]).
在幾何體顯示之後,按兩次Y可以將幾何體與Y軸的負半軸對齊。在調整好觀看視角之後,按K鍵鎖定視圖並切換到選擇模式。
提示
在實際的選取區域的操作中,一般都是使用正交投影模型(orthographic projection model.)將幾何體與任意軸對齊。這個技巧可以避免由於透視投影帶來自遮擋問題,使得選取變得容易。
在選擇區域時,可以用滑鼠拖動(矩形區域)或者 ctrl + 滑鼠左鍵點擊(選取多邊形區域)。下面的例子展現了多邊形選取。
注意選擇的區域為深色陰影,如果要保存選取的區域並且丟棄其餘的,請按C。他會彈出一個對話框去保存裁剪的區域。裁剪的結果將在顯示之後保存。
按F可以結束選擇模式進入自由瀏覽模式。
手動配准
選取對應點
下面的程式碼使用點對點的ICP去配准兩個點雲。它通過人工交互來獲得初始的對齊。
def demo_manual_registration():
print("手動ICP演示")
# 載入點雲
source = o3d.io.read_point_cloud("../../test_data/ICP/cloud_bin_0.pcd")
target = o3d.io.read_point_cloud("../../test_data/ICP/cloud_bin_2.pcd")
print("手動對齊前兩點雲的可視化")
draw_registration_result(source, target, np.identity(4))
# 從兩點雲中拾取點並建立對應關係
picked_id_source = pick_points(source)
picked_id_target = pick_points(target)
這個腳本讀取兩組點雲,並且在對齊之前可視化。
def pick_points(pcd):
print("")
print(
"1) 請使用至少選擇三個對應關係 [shift + 左擊]"
)
print(" 按 [shift + 右擊] 撤銷拾取的點")
print("2) 拾取點後,按「Q」關閉窗口")
vis = o3d.visualization.VisualizerWithEditing()
vis.create_window()
vis.add_geometry(pcd)
# 激活窗口。此函數將阻止當前執行緒,直到窗口關閉。
vis.run() # 等待用戶拾取點
vis.destroy_window()
print("")
return vis.get_picked_points()
函數pick_points(pcd)
創造了一個VisualizerWithEditing
實例去模仿draw_geometries
,他創造可視化窗口,添加幾何圖形,可視化幾何圖形和結束。VisualizerWithEditing
提供一種新的交互函數get_picked_points()
,他可以返回用戶選取的頂點的索引。
在窗口中點擊 shift + 左鍵可以選取頂點。當頂點被選取的時候,可視化窗口會在上面覆蓋一個球形。比如,下圖是在源點雲上選取了三個頂點之後的結果。
將會列印出:
[Open3D INFO] Picked point #58900 (2.1, 1.6, 1.5) to add in queue.
[Open3D INFO] Picked point #43151 (3.3, 1.5, 1.5) to add in queue.
[Open3D INFO] Picked point #76877 (2.9, 1.9, 1.1) to add in queue.
按 q 關閉窗口,之後在目標點雲上選取相應的對應點。這個球體的顏色有助於識別相同的對應點。
將會列印出:
[Open3D INFO] Picked point #48028 (1.6, 1.8, 1.3) to add in queue.
[Open3D INFO] Picked point #47210 (2.7, 1.7, 1.4) to add in queue.
[Open3D INFO] Picked point #98733 (2.4, 2.2, 1.1) to add in queue.
提示
為了有一個好的配准結果,應該去選取場景中均勻分散的三個對應點。選取拐角區域的頂點有助於選取高品質的對應點。
使用用戶選取的對應關係配准
assert (len(picked_id_source) >= 3 and len(picked_id_target) >= 3)
assert (len(picked_id_source) == len(picked_id_target))
corr = np.zeros((len(picked_id_source), 2))
corr[:, 0] = picked_id_source
corr[:, 1] = picked_id_target
# 利用對應關係估計粗變換
print("使用用戶給定的對應關係計算粗糙變換")
p2p = o3d.pipelines.registration.TransformationEstimationPointToPoint()
trans_init = p2p.compute_transformation(source, target,
o3d.utility.Vector2iVector(corr))
# 用於改善的點對點ICP
print("執行點對點ICP改善")
threshold = 0.03 # 3cm距離閾值
reg_p2p = o3d.pipelines.registration.registration_icp(
source, target, threshold, trans_init,
o3d.pipelines.registration.TransformationEstimationPointToPoint())
draw_registration_result(source, target, reg_p2p.transformation)
print("")
Demo的後續部分是根據用戶提供的對應關係來計算初始化轉換。這個腳本通過使用Vector2iVector(corr)
建立了成對的對應關係。他利用TransformationEstimationPointToPoint.compute_transformation
去計算一個初始化的變換。之後再此基礎上使用registration_icp
微調。
配准結果如下:
//www.dtmao.cc/news_show_689725.shtml