def test_to_legacy_pointcloud(device): dtype = o3c.Dtype.Float32 pcd = o3d.tgeometry.PointCloud(dtype, device) pcd.point["points"] = o3c.TensorList.from_tensor( o3c.Tensor([ [0, 1, 2], [3, 4, 5], ], dtype, device)) pcd.point["colors"] = o3c.TensorList.from_tensor( o3c.Tensor([ [6, 7, 8], [9, 10, 11], ], dtype, device)) legacy_pcd = pcd.to_legacy_pointcloud() np.testing.assert_allclose(np.asarray(legacy_pcd.points), np.array([ [0, 1, 2], [3, 4, 5], ])) np.testing.assert_allclose(np.asarray(legacy_pcd.colors), np.array([ [6, 7, 8], [9, 10, 11], ]))
def test_constructor_and_accessors(device): dtype = o3c.Dtype.Float32 # Constructor. pcd = o3d.tgeometry.PointCloud(dtype, device) assert "points" in pcd.point assert "colors" not in pcd.point assert isinstance(pcd.point, o3d.tgeometry.TensorListMap) assert isinstance(pcd.point["points"], o3c.TensorList) # Assignment. pcd.point["points"] = o3c.TensorList(o3c.SizeVector([3]), dtype, device) pcd.point["colors"] = o3c.TensorList(o3c.SizeVector([3]), dtype, device) assert len(pcd.point["points"]) == 0 assert len(pcd.point["colors"]) == 0 one_point = o3c.Tensor.ones((3, ), dtype, device) one_color = o3c.Tensor.ones((3, ), dtype, device) pcd.point["points"].push_back(one_point) pcd.point["colors"].push_back(one_color) assert len(pcd.point["points"]) == 1 assert len(pcd.point["colors"]) == 1 # Edit and access values. pcd.point["points"][0] = o3c.Tensor([1, 2, 3], dtype, device) assert pcd.point["points"][0].allclose(o3c.Tensor([1, 2, 3], dtype, device)) # Pushback. pcd.synchronized_push_back({"points": one_point, "colors": one_color}) assert len(pcd.point["points"]) == 2 assert len(pcd.point["colors"]) == 2
def test_erase(device): capacity = 10 hashmap = o3c.Hashmap(capacity, o3c.int64, o3c.int64, [1], [1], device) keys = o3c.Tensor([100, 300, 500, 700, 900], dtype=o3c.int64, device=device) values = o3c.Tensor([1, 3, 5, 7, 9], dtype=o3c.int64, device=device) hashmap.insert(keys, values) keys = o3c.Tensor([100, 200, 500], dtype=o3c.int64, device=device) masks = hashmap.erase(keys) np.testing.assert_equal(masks.cpu().numpy(), np.array([True, False, True])) assert hashmap.size() == 3 active_addrs = hashmap.get_active_addrs() active_indices = active_addrs.to(o3c.int64) active_keys = hashmap.get_key_tensor()[active_indices] active_values = hashmap.get_value_tensor()[active_indices] active_keys_np = active_keys.cpu().numpy().flatten() active_values_np = active_values.cpu().numpy().flatten() sorted_i = np.argsort(active_keys_np) np.testing.assert_equal(active_keys_np[sorted_i], np.array([300, 700, 900])) np.testing.assert_equal(active_values_np[sorted_i], np.array([3, 7, 9]))
def test_iterator(device): # 0-d. o3_t = o3c.Tensor.ones((), dtype=o3c.float32, device=device) with pytest.raises(Exception, match=r'Cannot iterate a scalar'): for o3_t_slice in o3_t: pass # 1-d. o3_t = o3c.Tensor([0, 1, 2], device=device) np_t = np.array([0, 1, 2]) for o3_t_slice, np_t_slice in zip(o3_t, np_t): np.testing.assert_equal(o3_t_slice.cpu().numpy(), np_t_slice) # TODO: 1-d with assignment (assigning to a 0-d slice) is not possible with # our current slice API. This issue is not related to the iterator. # Operator [:] requires 1 or more dimensions. We need to implement the [...] # operator. See: https://stackoverflow.com/a/49581266/1255535. # 2-d. o3_t = o3c.Tensor([[0, 1, 2], [3, 4, 5]], device=device) np_t = np.array([[0, 1, 2], [3, 4, 5]]) for o3_t_slice, np_t_slice in zip(o3_t, np_t): np.testing.assert_equal(o3_t_slice.cpu().numpy(), np_t_slice) # 2-d with assignment. o3_t = o3c.Tensor([[0, 1, 2], [3, 4, 5]], device=device) new_o3_t_slices = [ o3c.Tensor([0, 10, 20], device=device), o3c.Tensor([30, 40, 50], device=device) ] for o3_t_slice, new_o3_t_slice in zip(o3_t, new_o3_t_slices): o3_t_slice[:] = new_o3_t_slice np.testing.assert_equal(o3_t.cpu().numpy(), np.array([[0, 10, 20], [30, 40, 50]]))
def test_fixed_radius_search_random(dtype): if o3c.cuda.device_count() > 0: dataset_size, query_size = 1000, 100 radius = 0.1 dataset_np = np.random.rand(dataset_size, 3) dataset_points = o3c.Tensor(dataset_np, dtype=dtype) dataset_points_cuda = dataset_points.cuda() nns = o3c.nns.NearestNeighborSearch(dataset_points) nns_cuda = o3c.nns.NearestNeighborSearch(dataset_points_cuda) for _ in range(10): query_np = np.random.rand(query_size, 3) query_points = o3c.Tensor(query_np, dtype=dtype) query_points_cuda = query_points.cuda() nns.fixed_radius_index(radius) indices, distances, neighbors_row_splits = nns.fixed_radius_search( query_points, radius) nns_cuda.fixed_radius_index(radius) indices_cuda, distances_cuda, neighbors_row_splits_cuda = nns_cuda.fixed_radius_search( query_points_cuda, radius) np.testing.assert_equal(neighbors_row_splits.numpy(), neighbors_row_splits_cuda.cpu().numpy()) np.testing.assert_allclose(distances.numpy(), distances_cuda.cpu().numpy(), rtol=1e-5, atol=0) np.testing.assert_equal(indices.numpy(), indices_cuda.cpu().numpy())
def test_multivalue(device): capacity = 10 hashmap = o3c.HashMap(capacity, o3c.int64, (3), (o3c.int64, o3c.float64), ((1), (1)), device) keys = o3c.Tensor([[1, 2, 3], [2, 3, 4], [3, 4, 5]], dtype=o3c.int64, device=device) values_i64 = o3c.Tensor([1, 2, 3], dtype=o3c.int64, device=device) values_f64 = o3c.Tensor([400.0, 500.0, 600.0], dtype=o3c.float64, device=device) buf_indices, masks = hashmap.insert(keys, [values_i64, values_f64]) assert masks.to(o3c.int64).sum() == 3 valid_indices = buf_indices[masks].to(o3c.int64) valid_keys = hashmap.key_tensor()[valid_indices, :] valid_values_i64 = hashmap.value_tensor(0)[valid_indices] valid_values_f64 = hashmap.value_tensor(1)[valid_indices] np.testing.assert_equal( valid_keys.cpu().numpy().flatten(), np.array([[1, 2, 3], [2, 3, 4], [3, 4, 5]]).flatten()) np.testing.assert_equal(valid_values_i64.cpu().numpy().flatten(), np.array([1, 2, 3])) np.testing.assert_allclose(valid_values_f64.cpu().numpy().flatten(), np.array([400.0, 500.0, 600.0])) keys = o3c.Tensor([[1, 2, 3], [4, 5, 6]], dtype=o3c.int64, device=device) masks = hashmap.erase(keys) np.testing.assert_equal(masks.cpu().numpy().flatten(), np.array([True, False]))
def test_constructor_and_accessors(device): dtype = o3c.float32 # Constructor. pcd = o3d.t.geometry.PointCloud(device) assert "positions" not in pcd.point assert "colors" not in pcd.point assert isinstance(pcd.point, o3d.t.geometry.TensorMap) # Assignment. pcd.point["positions"] = o3c.Tensor.ones((0, 3), dtype, device) pcd.point["colors"] = o3c.Tensor.ones((0, 3), dtype, device) assert len(pcd.point["positions"]) == 0 assert len(pcd.point["colors"]) == 0 pcd.point["positions"] = o3c.Tensor.ones((1, 3), dtype, device) pcd.point["colors"] = o3c.Tensor.ones((1, 3), dtype, device) assert len(pcd.point["positions"]) == 1 assert len(pcd.point["colors"]) == 1 # Edit and access values. points = pcd.point["positions"] points[0] = o3c.Tensor([1, 2, 3], dtype, device) assert pcd.point["positions"].allclose( o3c.Tensor([[1, 2, 3]], dtype, device))
def test_complex_shape(device): capacity = 10 hashmap = o3c.Hashmap(capacity, o3c.int64, o3c.int64, [3], [1], device) keys = o3c.Tensor([[1, 2, 3], [2, 3, 4], [3, 4, 5]], dtype=o3c.int64, device=device) values = o3c.Tensor([1, 2, 3], dtype=o3c.int64, device=device) addrs, masks = hashmap.insert(keys, values) assert masks.to(o3c.int64).sum() == 3 valid_indices = addrs[masks].to(o3c.int64) valid_keys = hashmap.get_key_tensor()[valid_indices, :] valid_values = hashmap.get_value_tensor()[valid_indices] np.testing.assert_equal( valid_keys.cpu().numpy().flatten(), np.array([[1, 2, 3], [2, 3, 4], [3, 4, 5]]).flatten()) np.testing.assert_equal(valid_values.cpu().numpy().flatten(), np.array([1, 2, 3])) keys = o3c.Tensor([[1, 2, 3], [4, 5, 6]], dtype=o3c.int64, device=device) masks = hashmap.erase(keys) np.testing.assert_equal(masks.cpu().numpy().flatten(), np.array([True, False]))
def test_create_box(device): # Test with default parameters. box_default = o3d.t.geometry.TriangleMesh.create_box(device=device) vertex_positions_default = o3c.Tensor( [[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0], [1.0, 0.0, 1.0], [0.0, 1.0, 0.0], [1.0, 1.0, 0.0], [0.0, 1.0, 1.0], [1.0, 1.0, 1.0]], o3c.float32, device) triangle_indices_default = o3c.Tensor( [[4, 7, 5], [4, 6, 7], [0, 2, 4], [2, 6, 4], [0, 1, 2], [1, 3, 2], [1, 5, 7], [1, 7, 3], [2, 3, 7], [2, 7, 6], [0, 4, 1], [1, 4, 5]], o3c.int64, device) assert box_default.vertex['positions'].allclose(vertex_positions_default) assert box_default.triangle['indices'].allclose(triangle_indices_default) # Test with custom parameters. box_custom = o3d.t.geometry.TriangleMesh.create_box( 2, 3, 4, o3c.float64, o3c.int32, device) vertex_positions_custom = o3c.Tensor( [[0.0, 0.0, 0.0], [2.0, 0.0, 0.0], [0.0, 0.0, 4.0], [2.0, 0.0, 4.0], [0.0, 3.0, 0.0], [2.0, 3.0, 0.0], [0.0, 3.0, 4.0], [2.0, 3.0, 4.0]], o3c.float64, device) triangle_indices_custom = o3c.Tensor( [[4, 7, 5], [4, 6, 7], [0, 2, 4], [2, 6, 4], [0, 1, 2], [1, 3, 2], [1, 5, 7], [1, 7, 3], [2, 3, 7], [2, 7, 6], [0, 4, 1], [1, 4, 5]], o3c.int32, device) assert box_custom.vertex['positions'].allclose(vertex_positions_custom) assert box_custom.triangle['indices'].allclose(triangle_indices_custom)
def test_lu_ipiv(device, dtype): a = o3c.Tensor([[2, 3, 1], [3, 3, 1], [2, 4, 1]], dtype=dtype, device=device) if dtype in [o3c.int32, o3c.int64]: with pytest.raises(RuntimeError) as excinfo: o3c.lu_ipiv(a) assert 'Only tensors with Float32 or Float64 are supported' in str( excinfo.value) return ipiv, a_lu = o3c.lu_ipiv(a) a_lu_ = o3c.Tensor([[3.0, 3.0, 1.0], [0.666667, 2.0, 0.333333], [0.666667, 0.5, 0.166667]], dtype=dtype) ipiv_ = o3c.Tensor([2, 3, 3], dtype=dtype) np.testing.assert_allclose(a_lu.cpu().numpy(), a_lu_.numpy(), rtol=1e-5, atol=1e-5) np.testing.assert_allclose(ipiv.cpu().numpy(), ipiv_.numpy(), 1e-6) # Non-2D for shape in [(), [1], (3, 4, 5)]: with pytest.raises(RuntimeError) as excinfo: a_ = o3c.Tensor.zeros(shape, dtype=dtype, device=device) o3c.lu_ipiv(a_) assert 'must be 2D' in str(excinfo.value)
def test_from_legacy_pointcloud(device): dtype = o3c.Dtype.Float32 legacy_pcd = o3d.geometry.PointCloud() legacy_pcd.points = o3d.utility.Vector3dVector( np.array([ [0, 1, 2], [3, 4, 5], ])) legacy_pcd.colors = o3d.utility.Vector3dVector( np.array([ [6, 7, 8], [9, 10, 11], ])) pcd = o3d.tgeometry.PointCloud.from_legacy_pointcloud( legacy_pcd, dtype, device) assert pcd.point["points"].as_tensor().allclose( o3c.Tensor([ [0, 1, 2], [3, 4, 5], ], dtype, device)) assert pcd.point["colors"].as_tensor().allclose( o3c.Tensor([ [6, 7, 8], [9, 10, 11], ], dtype, device))
def get_pcds(dtype, device): source_points = o3c.Tensor( [[1.0, 0.5, 2.0], [0.5, 0.5, 2.0], [0.5, 0.5, 2.5], [3.0, 1.0, 1.5], [3.5, 1.0, 1.0], [0.5, 1.0, 2.0], [1.5, 1.0, 1.5], [2.0, 1.0, 1.5], [1.0, 1.0, 2.0], [2.5, 1.0, 1.5], [3.0, 1.0, 1.0], [0.5, 1.0, 2.5], [1.0, 1.0, 1.0], [1.5, 1.0, 1.0], [1.0, 1.5, 1.0], [3.0, 1.5, 1.0], [3.5, 1.5, 1.0], [3.0, 1.5, 1.5], [0.5, 1.5, 1.5], [0.5, 1.5, 2.0], [1.0, 1.5, 2.0], [2.5, 1.5, 1.5], [1.5, 1.5, 1.0], [1.5, 1.5, 1.5], [2.0, 1.5, 1.5], [3.0, 1.5, 0.5], [2.5, 1.5, 1.0], [2.0, 1.5, 1.0], [3.0, 2.0, 0.5], [0.5, 2.0, 1.5], [3.0, 2.0, 1.0], [1.0, 2.0, 1.0], [2.0, 1.5, 0.5], [0.5, 2.0, 2.0], [2.5, 2.0, 1.0], [2.5, 2.0, 0.5], [2.0, 2.0, 0.5], [2.5, 1.5, 0.5], [3.0, 2.0, 1.5], [2.0, 2.0, 1.0], [1.0, 2.0, 2.0], [1.5, 2.0, 1.0], [1.5, 2.0, 1.5], [2.5, 2.0, 1.5], [2.0, 2.0, 1.5], [1.0, 2.0, 0.5], [0.5, 2.0, 1.0], [1.5, 2.0, 0.5], [1.0, 2.0, 1.5]], dtype, device) target_points = o3c.Tensor( [[1.5, 1.0, 1.5], [2.5, 1.0, 1.5], [1.5, 1.0, 1.0], [1.0, 1.0, 1.0], [2.0, 1.0, 1.5], [3.0, 1.0, 1.5], [1.0, 1.0, 0.5], [1.0, 1.5, 1.0], [1.0, 1.5, 0.5], [1.0, 1.0, 1.5], [3.0, 1.0, 2.0], [3.0, 1.5, 2.0], [3.0, 1.5, 1.5], [1.0, 1.5, 1.5], [1.5, 1.5, 1.5], [2.5, 1.5, 1.5], [2.0, 1.5, 1.5], [1.5, 1.5, 1.0], [2.5, 1.5, 2.0], [1.0, 2.0, 1.0], [1.0, 2.0, 0.5], [2.5, 1.5, 1.0], [3.0, 2.0, 1.5], [2.5, 2.0, 1.0], [2.5, 2.0, 1.5], [1.5, 2.0, 1.0], [2.0, 1.5, 1.0], [1.0, 2.0, 1.5], [2.0, 2.0, 1.0], [1.5, 2.0, 1.5], [1.5, 2.0, 0.5], [2.0, 2.0, 1.5], [2.0, 2.0, 0.5], [1.5, 2.5, 1.0], [1.0, 2.5, 1.0], [3.0, 2.0, 1.0], [2.0, 2.5, 1.0], [2.5, 2.5, 1.0]], dtype, device) target_normals = o3c.Tensor( [[0.15597, -0.0463812, -0.986672], [-0.213545, 0.887963, 0.407334], [0.423193, -0.121977, -0.897792], [0.202251, 0.27611, -0.939605], [0.275452, 0.207216, -0.938716], [0.326146, 0.0385317, -0.944534], [0.983129, -0.174668, -0.0543011], [0.898665, -0.0602029, 0.434485], [0.711325, 0.193223, -0.675783], [0.346158, 0.198724, -0.916888], [0.302085, 0.28938, -0.908297], [0.341044, 0.414138, -0.843907], [0.212191, 0.213068, -0.953717], [0.239759, 0.313187, -0.918929], [0.302290, 0.27265, -0.913391], [0.209796, 0.402747, -0.890944], [0.267025, 0.218226, -0.938656], [0.00126928, -0.976587, -0.21512], [0.321912, 0.194736, -0.926526], [0.831227, 0.236675, -0.503037], [0.987006, -0.155324, 0.0411639], [0.103384, -0.808796, -0.57893], [0.181245, 0.66226, -0.727023], [0.235471, 0.525053, -0.817846], [0.231954, 0.446165, -0.864369], [-0.261931, -0.725542, -0.636381], [0.120953, -0.864985, -0.487003], [0.858345, -0.227847, 0.459706], [-0.416259, -0.367408, -0.831709], [-0.476652, 0.206048, -0.854604], [-0.211959, -0.523378, -0.825317], [-0.964914, 0.0541031, -0.256931], [-0.0653566, -0.913961, -0.400504], [-0.846868, -0.170805, -0.503628], [0.0366971, 0.515834, -0.855902], [-0.0714554, -0.855019, -0.513651], [-0.0217377, -0.957744, -0.286799], [-0.0345231, -0.947096, -0.319088]], dtype, device) source = o3d.t.geometry.PointCloud(device) target = o3d.t.geometry.PointCloud(device) source.point["positions"] = source_points target.point["positions"] = target_points target.point["normals"] = target_normals return source, target
def test_svd(device, dtype): a = o3c.Tensor([[2, 4], [1, 3], [0, 0], [0, 0]], dtype=dtype, device=device) if dtype in [o3c.int32, o3c.int64]: with pytest.raises(RuntimeError) as excinfo: o3c.svd(a) assert 'Only tensors with Float32 or Float64 are supported' in str( excinfo.value) return u, s, vt = o3c.svd(a) assert u.shape == o3c.SizeVector([4, 4]) assert s.shape == o3c.SizeVector([2]) assert vt.shape == o3c.SizeVector([2, 2]) # u and vt are orthogonal matrices uut = u @ u.T() eye_uut = o3c.Tensor.eye(4, dtype=dtype) np.testing.assert_allclose(uut.cpu().numpy(), eye_uut.cpu().numpy(), atol=1e-6) vvt = vt.T() @ vt eye_vvt = o3c.Tensor.eye(2, dtype=dtype) np.testing.assert_allclose(vvt.cpu().numpy(), eye_vvt.cpu().numpy(), atol=1e-6) usvt = u[:, :2] @ o3c.Tensor.diag(s) @ vt # The accuracy of svd over Float32 is very low... np.testing.assert_allclose(a.cpu().numpy(), usvt.cpu().numpy(), atol=1e-5) u = u.cpu().numpy() s = s.cpu().numpy() vt = vt.cpu().numpy() u_numpy, s_numpy, vt_numpy = np.linalg.svd(a.cpu().numpy()) # u, vt can be different by several signs np.testing.assert_allclose(np.abs(u), np.abs(u_numpy), 1e-6) np.testing.assert_allclose(np.abs(vt), np.abs(vt_numpy), 1e-6) np.testing.assert_allclose(s, s_numpy, 1e-6) for shapes in [(0, 0), (0, 2)]: with pytest.raises(RuntimeError) as excinfo: a = o3c.Tensor.zeros(shapes, dtype=dtype, device=device) a.svd() assert 'dimensions with zero' in str(excinfo.value) for shapes in [(), [1], (1, 2, 4)]: with pytest.raises(RuntimeError) as excinfo: a = o3c.Tensor.zeros(shapes, dtype=dtype, device=device) a.svd() assert 'must be 2D' in str(excinfo.value) with pytest.raises(RuntimeError) as excinfo: a = o3c.Tensor(shapes, dtype=dtype, device=device) a.svd() assert 'must be 2D' in str(excinfo.value)
def test_binary_ew_ops(benchmark, size, dtype, op): np_a = np.array(np.random.uniform(1, 127, size), dtype=to_numpy_dtype(dtype)) np_b = np.array(np.random.uniform(1, 127, size), dtype=to_numpy_dtype(dtype)) a = o3c.Tensor(np_a, dtype=dtype, device=o3c.Device("CPU:0")) b = o3c.Tensor(np_b, dtype=dtype, device=o3c.Device("CPU:0")) benchmark(op, a, b)
def test_hybrid_search(benchmark, size, dtype, device): nns_opt = dict(knn=1, radius=0.01) np_a = np.array(np.random.rand(size, 3), dtype=to_numpy_dtype(dtype)) np_b = np.array(np.random.rand(size, 3), dtype=to_numpy_dtype(dtype)) a = o3c.Tensor(np_a, dtype=dtype, device=device) b = o3c.Tensor(np_b, dtype=dtype, device=device) index = NNSOps.hybrid_setup(a, nns_opt) benchmark(NNSOps.hybrid_search, index, b, nns_opt)
def test_test_registration_icp_point_to_plane(device): dtype = o3c.Dtype.Float32 source_points = o3c.Tensor( [[1.15495, 2.40671, 1.15061], [1.81481, 2.06281, 1.71927], [0.888322, 2.05068, 2.04879], [3.78842, 1.70788, 1.30246], [1.8437, 2.22894, 0.986237], [2.95706, 2.2018, 0.987878], [1.72644, 1.24356, 1.93486], [0.922024, 1.14872, 2.34317], [3.70293, 1.85134, 1.15357], [3.06505, 1.30386, 1.55279], [0.634826, 1.04995, 2.47046], [1.40107, 1.37469, 1.09687], [2.93002, 1.96242, 1.48532], [3.74384, 1.30258, 1.30244]], dtype, device) target_points = o3c.Tensor( [[2.41766, 2.05397, 1.74994], [1.37848, 2.19793, 1.66553], [2.24325, 2.27183, 1.33708], [3.09898, 1.98482, 1.77401], [1.81615, 1.48337, 1.49697], [3.01758, 2.20312, 1.51502], [2.38836, 1.39096, 1.74914], [1.30911, 1.4252, 1.37429], [3.16847, 1.39194, 1.90959], [1.59412, 1.53304, 1.5804], [1.34342, 2.19027, 1.30075]], dtype, device) target_normals = o3c.Tensor( [[-0.0085016, -0.22355, -0.519574], [0.257463, -0.0738755, -0.698319], [0.0574301, -0.484248, -0.409929], [-0.0123503, -0.230172, -0.52072], [0.355904, -0.142007, -0.720467], [0.0674038, -0.418757, -0.458602], [0.226091, 0.258253, -0.874024], [0.43979, 0.122441, -0.574998], [0.109144, 0.180992, -0.762368], [0.273325, 0.292013, -0.903111], [0.385407, -0.212348, -0.277818]], dtype, device) source_t = o3d.t.geometry.PointCloud(device) target_t = o3d.t.geometry.PointCloud(device) source_t.point["points"] = source_points target_t.point["points"] = target_points target_t.point["normals"] = target_normals source_legacy = source_t.to_legacy_pointcloud() target_legacy = target_t.to_legacy_pointcloud() max_correspondence_distance = 1.25 init_trans_legacy = np.eye(4) init_trans_t = o3c.Tensor.eye(4, o3c.Dtype.Float64, device) reg_p2plane_t = o3d.t.pipelines.registration.registration_icp( source_t, target_t, max_correspondence_distance, init_trans_t, o3d.t.pipelines.registration.TransformationEstimationPointToPlane(), o3d.t.pipelines.registration.ICPConvergenceCriteria(max_iteration=2)) reg_p2plane_legacy = o3d.pipelines.registration.registration_icp( source_legacy, target_legacy, max_correspondence_distance, init_trans_legacy, o3d.pipelines.registration.TransformationEstimationPointToPlane(), o3d.pipelines.registration.ICPConvergenceCriteria(max_iteration=2)) np.testing.assert_allclose(reg_p2plane_t.inlier_rmse, reg_p2plane_legacy.inlier_rmse, 0.0001) np.testing.assert_allclose(reg_p2plane_t.fitness, reg_p2plane_legacy.fitness, 0.0001)
def test_compute_transformation_point_to_plane(device): dtype = o3c.Dtype.Float32 source_points = o3c.Tensor( [[1.15495, 2.40671, 1.15061], [1.81481, 2.06281, 1.71927], [0.888322, 2.05068, 2.04879], [3.78842, 1.70788, 1.30246], [1.8437, 2.22894, 0.986237], [2.95706, 2.2018, 0.987878], [1.72644, 1.24356, 1.93486], [0.922024, 1.14872, 2.34317], [3.70293, 1.85134, 1.15357], [3.06505, 1.30386, 1.55279], [0.634826, 1.04995, 2.47046], [1.40107, 1.37469, 1.09687], [2.93002, 1.96242, 1.48532], [3.74384, 1.30258, 1.30244]], dtype, device) target_points = o3c.Tensor( [[2.41766, 2.05397, 1.74994], [1.37848, 2.19793, 1.66553], [2.24325, 2.27183, 1.33708], [3.09898, 1.98482, 1.77401], [1.81615, 1.48337, 1.49697], [3.01758, 2.20312, 1.51502], [2.38836, 1.39096, 1.74914], [1.30911, 1.4252, 1.37429], [3.16847, 1.39194, 1.90959], [1.59412, 1.53304, 1.5804], [1.34342, 2.19027, 1.30075]], dtype, device) target_normals = o3c.Tensor( [[-0.0085016, -0.22355, -0.519574], [0.257463, -0.0738755, -0.698319], [0.0574301, -0.484248, -0.409929], [-0.0123503, -0.230172, -0.52072], [0.355904, -0.142007, -0.720467], [0.0674038, -0.418757, -0.458602], [0.226091, 0.258253, -0.874024], [0.43979, 0.122441, -0.574998], [0.109144, 0.180992, -0.762368], [0.273325, 0.292013, -0.903111], [0.385407, -0.212348, -0.277818]], dtype, device) source_t = o3d.t.geometry.PointCloud(device) target_t = o3d.t.geometry.PointCloud(device) source_t.point["points"] = source_points target_t.point["points"] = target_points target_t.point["normals"] = target_normals corres_first = o3c.Tensor([0, 1, 2, 3, 4, 5, 6, 8, 9, 11, 12, 13], o3c.Dtype.Int64, device) corres_second = o3c.Tensor([10, 1, 1, 3, 2, 5, 9, 5, 8, 7, 5, 8], o3c.Dtype.Int64, device) corres = corres_first, corres_second estimation_p2l = o3d.t.pipelines.registration.TransformationEstimationPointToPlane( ) transformation_p2l = estimation_p2l.compute_transformation( source_t, target_t, corres) source_transformed_p2l = source_t.transform( transformation_p2l.to(device, dtype)) p2l_rmse = estimation_p2l.compute_rmse(source_transformed_p2l, target_t, corres) np.testing.assert_allclose(p2l_rmse, 0.41425, 0.0001)
def test_to_legacy(device): dtype = o3c.float32 pcd = o3d.t.geometry.PointCloud(device) pcd.point["positions"] = o3c.Tensor([[0, 1, 2], [3, 4, 5]], dtype, device) pcd.point["colors"] = o3c.Tensor([[6, 7, 8], [9, 10, 11]], dtype, device) legacy_pcd = pcd.to_legacy() np.testing.assert_allclose(np.asarray(legacy_pcd.points), np.array([[0, 1, 2], [3, 4, 5]])) np.testing.assert_allclose(np.asarray(legacy_pcd.colors), np.array([[6, 7, 8], [9, 10, 11]]))
def test_all_any(device): a = o3c.Tensor([False, True, True, True], dtype=o3c.bool, device=device) assert not a.all() assert a.any() a = o3c.Tensor([True, True, True, True], dtype=o3c.bool, device=device) assert a.all() # Empty a = o3c.Tensor([], dtype=o3c.bool, device=device) assert a.all() assert not a.any()
def test_comparision_ops(device): np_a = np.array([0, 1, -1]) np_b = np.array([0, 0, 0]) o3_a = o3c.Tensor(np_a, device=device) o3_b = o3c.Tensor(np_b, device=device) np.testing.assert_equal((o3_a > o3_b).cpu().numpy(), np_a > np_b) np.testing.assert_equal((o3_a >= o3_b).cpu().numpy(), np_a >= np_b) np.testing.assert_equal((o3_a < o3_b).cpu().numpy(), np_a < np_b) np.testing.assert_equal((o3_a <= o3_b).cpu().numpy(), np_a <= np_b) np.testing.assert_equal((o3_a == o3_b).cpu().numpy(), np_a == np_b) np.testing.assert_equal((o3_a != o3_b).cpu().numpy(), np_a != np_b)
def test_solve(device, dtype): # Test square a = o3c.Tensor([[3, 1], [1, 2]], dtype=dtype, device=device) b = o3c.Tensor([9, 8], dtype=dtype, device=device) x = o3c.solve(a, b) x_numpy = np.linalg.solve(a.cpu().numpy(), b.cpu().numpy()) np.testing.assert_allclose(x.cpu().numpy(), x_numpy, atol=1e-6) with pytest.raises(RuntimeError) as excinfo: a = o3c.Tensor.zeros((3, 3), dtype=dtype, device=device) b = o3c.Tensor.ones((3, ), dtype=dtype, device=device) x = o3c.solve(a, b) assert 'singular' in str(excinfo.value)
def test_registration_icp_point_to_point(device): dtype = o3c.Dtype.Float32 source_points = o3c.Tensor( [[1.15495, 2.40671, 1.15061], [1.81481, 2.06281, 1.71927], [0.888322, 2.05068, 2.04879], [3.78842, 1.70788, 1.30246], [1.8437, 2.22894, 0.986237], [2.95706, 2.2018, 0.987878], [1.72644, 1.24356, 1.93486], [0.922024, 1.14872, 2.34317], [3.70293, 1.85134, 1.15357], [3.06505, 1.30386, 1.55279], [0.634826, 1.04995, 2.47046], [1.40107, 1.37469, 1.09687], [2.93002, 1.96242, 1.48532], [3.74384, 1.30258, 1.30244]], dtype, device) target_points = o3c.Tensor( [[2.41766, 2.05397, 1.74994], [1.37848, 2.19793, 1.66553], [2.24325, 2.27183, 1.33708], [3.09898, 1.98482, 1.77401], [1.81615, 1.48337, 1.49697], [3.01758, 2.20312, 1.51502], [2.38836, 1.39096, 1.74914], [1.30911, 1.4252, 1.37429], [3.16847, 1.39194, 1.90959], [1.59412, 1.53304, 1.5804], [1.34342, 2.19027, 1.30075]], dtype, device) source_t = o3d.t.geometry.PointCloud(device) target_t = o3d.t.geometry.PointCloud(device) source_t.point["points"] = source_points target_t.point["points"] = target_points source_legacy = source_t.to_legacy_pointcloud() target_legacy = target_t.to_legacy_pointcloud() max_correspondence_distance = 1.25 init_trans_legacy = np.eye(4) init_trans_t = o3c.Tensor.eye(4, o3c.Dtype.Float64, device) reg_p2p_t = o3d.t.pipelines.registration.registration_icp( source_t, target_t, max_correspondence_distance, init_trans_t, o3d.t.pipelines.registration.TransformationEstimationPointToPoint(), o3d.t.pipelines.registration.ICPConvergenceCriteria(max_iteration=2)) reg_p2p_legacy = o3d.pipelines.registration.registration_icp( source_legacy, target_legacy, max_correspondence_distance, init_trans_legacy, o3d.pipelines.registration.TransformationEstimationPointToPoint(), o3d.pipelines.registration.ICPConvergenceCriteria(max_iteration=2)) np.testing.assert_allclose(reg_p2p_t.inlier_rmse, reg_p2p_legacy.inlier_rmse, 0.0001) np.testing.assert_allclose(reg_p2p_t.fitness, reg_p2p_legacy.fitness, 0.0001)
def test_matmul(device, dtype): # Shape takes tuple, list or o3c.SizeVector a = o3c.Tensor([[1, 2.5, 3], [4, 5, 6.2]], dtype=dtype, device=device) b = o3c.Tensor([[7.5, 8, 9, 10], [11, 12, 13, 14], [15, 16, 17.8, 18]], dtype=dtype, device=device) c = o3c.matmul(a, b) assert c.shape == o3c.SizeVector([2, 4]) c_numpy = a.cpu().numpy() @ b.cpu().numpy() np.testing.assert_allclose(c.cpu().numpy(), c_numpy, 1e-6) # Non-contiguous test a = a[:, 1:] b = b[[0, 2], :] c = a.matmul(b) assert c.shape == o3c.SizeVector([2, 4]) c_numpy = a.cpu().numpy() @ b.cpu().numpy() np.testing.assert_allclose(c.cpu().numpy(), c_numpy, 1e-6) # Incompatible shape test with pytest.raises(RuntimeError) as excinfo: a = o3c.Tensor.zeros((3, 4, 5), dtype=dtype) b = o3c.Tensor.zeros((4, 5), dtype=dtype) c = a @ b assert 'Tensor A must be 2D' in str(excinfo.value) with pytest.raises(RuntimeError) as excinfo: a = o3c.Tensor.zeros((3, 4), dtype=dtype) b = o3c.Tensor.zeros((4, 5, 6), dtype=dtype) c = a @ b assert 'Tensor B must be 1D (vector) or 2D (matrix)' in str( excinfo.value) with pytest.raises(RuntimeError) as excinfo: a = o3c.Tensor.zeros((3, 4), dtype=dtype) b = o3c.Tensor.zeros((3, 7), dtype=dtype) c = a @ b assert 'mismatch with' in str(excinfo.value) for shapes in [((0, 0), (0, 0)), ((2, 0), (0, 3)), ((0, 2), (2, 0)), ((2, 0), (0, 0))]: with pytest.raises(RuntimeError) as excinfo: a_shape, b_shape = shapes a = o3c.Tensor.zeros(a_shape, dtype=dtype, device=device) b = o3c.Tensor.zeros(b_shape, dtype=dtype, device=device) c = a @ b assert 'dimensions with zero' in str(excinfo.value)
def test_insertion(device): capacity = 10 hashmap = o3c.Hashmap(capacity, o3c.int64, o3c.int64, [1], [1], device) keys = o3c.Tensor([100, 300, 500, 700, 900, 900], dtype=o3c.int64, device=device) values = o3c.Tensor([1, 3, 5, 7, 9, 9], dtype=o3c.int64, device=device) addrs, masks = hashmap.insert(keys, values) assert masks.to(o3c.int64).sum() == 5 valid_indices = addrs[masks].to(o3c.int64) valid_keys = hashmap.get_key_tensor()[valid_indices] valid_values = hashmap.get_value_tensor()[valid_indices] np.testing.assert_equal(valid_keys.cpu().numpy(), valid_values.cpu().numpy() * 100)
def cast_to_py_tensor(c_tensor): if isinstance(c_tensor, o3d.pybind.core.Tensor): py_tensor = o3c.Tensor([]) py_tensor.shallow_copy_from(c_tensor) return py_tensor else: return c_tensor
def test_get_information_matrix(device): supported_dtypes = [o3c.float32, o3c.float64] for dtype in supported_dtypes: source_t, target_t = get_pcds(dtype, device) source_legacy = source_t.to_legacy() target_legacy = target_t.to_legacy() max_correspondence_distance = 3.0 transformation_legacy = np.array([[0.862, 0.011, -0.507, 0.5], [-0.139, 0.967, -0.215, 0.7], [0.487, 0.255, 0.835, -1.4], [0.0, 0.0, 0.0, 1.0]]) transformation_t = o3c.Tensor(transformation_legacy, dtype=o3c.float64, device=device) info_matrix_t = o3d.t.pipelines.registration.get_information_matrix( source_t, target_t, max_correspondence_distance, transformation_t) info_matrix_legacy = o3d.pipelines.registration.get_information_matrix_from_point_clouds( source_legacy, target_legacy, max_correspondence_distance, transformation_legacy) np.testing.assert_allclose(info_matrix_t.cpu().numpy(), info_matrix_legacy, 1e-1, 1e-1)
def test_non_zero(device): np_x = np.array([[3, 0, 0], [0, 4, 0], [5, 6, 0]]) np_nonzero_tuple = np.nonzero(np_x) o3_x = o3c.Tensor(np_x, device=device) o3_nonzero_tuple = o3_x.nonzero(as_tuple=True) for np_t, o3_t in zip(np_nonzero_tuple, o3_nonzero_tuple): np.testing.assert_equal(np_t, o3_t.cpu().numpy())
def test_reduction_prod(dim, keepdim, device): np_src = np.array(range(24)).reshape((2, 3, 4)) o3_src = o3c.Tensor(np_src, device=device) np_dst = np_src.prod(axis=dim, keepdims=keepdim) o3_dst = o3_src.prod(dim=dim, keepdim=keepdim) np.testing.assert_allclose(o3_dst.cpu().numpy(), np_dst)
def test_getitem(device): np_t = np.array(range(24)).reshape((2, 3, 4)) o3_t = o3c.Tensor(np_t, device=device) np.testing.assert_equal(o3_t[:].cpu().numpy(), np_t[:]) np.testing.assert_equal(o3_t[0].cpu().numpy(), np_t[0]) np.testing.assert_equal(o3_t[0, 1].cpu().numpy(), np_t[0, 1]) np.testing.assert_equal(o3_t[0, :].cpu().numpy(), np_t[0, :]) np.testing.assert_equal(o3_t[0, 1:3].cpu().numpy(), np_t[0, 1:3]) np.testing.assert_equal(o3_t[0, :, :-2].cpu().numpy(), np_t[0, :, :-2]) np.testing.assert_equal(o3_t[0, 1:3, 2].cpu().numpy(), np_t[0, 1:3, 2]) np.testing.assert_equal(o3_t[0, 1:-1, 2].cpu().numpy(), np_t[0, 1:-1, 2]) np.testing.assert_equal(o3_t[0, 1:3, 0:4:2].cpu().numpy(), np_t[0, 1:3, 0:4:2]) np.testing.assert_equal(o3_t[0, 1:3, 0:-1:2].cpu().numpy(), np_t[0, 1:3, 0:-1:2]) np.testing.assert_equal(o3_t[0, 1, :].cpu().numpy(), np_t[0, 1, :]) # Slice out-of-range np.testing.assert_equal(o3_t[1:6].cpu().numpy(), np_t[1:6]) np.testing.assert_equal(o3_t[2:5, -10:20].cpu().numpy(), np_t[2:5, -10:20]) np.testing.assert_equal(o3_t[2:2, 3:3, 4:4].cpu().numpy(), np_t[2:2, 3:3, 4:4]) np.testing.assert_equal(o3_t[2:20, 3:30, 4:40].cpu().numpy(), np_t[2:20, 3:30, 4:40]) np.testing.assert_equal(o3_t[-2:20, -3:30, -4:40].cpu().numpy(), np_t[-2:20, -3:30, -4:40]) # Slice the slice np.testing.assert_equal(o3_t[0:2, 1:3, 0:4][0:1, 0:2, 2:3].cpu().numpy(), np_t[0:2, 1:3, 0:4][0:1, 0:2, 2:3])
def test_unary_ew_ops(device): src_vals = np.array([0, 1, 2, 3, 4, 5]).astype(np.float32) src = o3c.Tensor(src_vals, device=device) rtol = 1e-5 atol = 0 np.testing.assert_allclose(src.sqrt().cpu().numpy(), np.sqrt(src_vals), rtol=rtol, atol=atol) np.testing.assert_allclose(src.sin().cpu().numpy(), np.sin(src_vals), rtol=rtol, atol=atol) np.testing.assert_allclose(src.cos().cpu().numpy(), np.cos(src_vals), rtol=rtol, atol=atol) np.testing.assert_allclose(src.neg().cpu().numpy(), -src_vals, rtol=rtol, atol=atol) np.testing.assert_allclose(src.exp().cpu().numpy(), np.exp(src_vals), rtol=rtol, atol=atol)