File: test_image.py

package info (click to toggle)
open3d 0.19.0-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 83,496 kB
  • sloc: cpp: 206,543; python: 27,254; ansic: 8,356; javascript: 1,883; sh: 1,527; makefile: 259; xml: 69
file content (131 lines) | stat: -rw-r--r-- 5,374 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# ----------------------------------------------------------------------------
# -                        Open3D: www.open3d.org                            -
# ----------------------------------------------------------------------------
# Copyright (c) 2018-2024 www.open3d.org
# SPDX-License-Identifier: MIT
# ----------------------------------------------------------------------------

import open3d as o3d
import open3d.core as o3c
from open3d.t.geometry import Image
import numpy as np
import pytest
import pickle
import tempfile

import sys
import os

sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../..")
from open3d_test import list_devices


@pytest.mark.parametrize("device", list_devices())
def test_to_linear_transform(device):
    TOL = {"rtol": 1e-7, "atol": 1e-7}
    # reference data
    input_data = np.array((10, 25, 0, 13, 5, 40), dtype=np.uint8).reshape(
        (2, 3, 1))
    output_ref = input_data / 255.
    negative_image_ref = 1. - input_data / 255.
    saturate_ref = np.array((180, 255, 0, 240, 80, 255),
                            dtype=np.uint8).reshape((2, 3, 1))

    t_input = o3c.Tensor(input_data, dtype=o3c.uint8, device=device)
    t_input3 = o3c.Tensor(np.broadcast_to(input_data, shape=(2, 3, 3)),
                          dtype=o3c.uint8,
                          device=device)

    input1 = Image(t_input)
    # UInt8 -> Float32: auto scale = 1./255
    output1 = input1.to(o3c.float32)
    assert output1.dtype == o3c.float32
    np.testing.assert_allclose(output1.as_tensor().cpu().numpy(), output_ref,
                               **TOL)
    # 3 channels
    input3 = Image(t_input3)
    output3 = input3.to(o3c.float32)
    np.testing.assert_allclose(output3.as_tensor().cpu().numpy(),
                               np.broadcast_to(output_ref, (2, 3, 3)), **TOL)

    # LinearTransform to negative image
    output1.linear_transform(scale=-1, offset=1)
    np.testing.assert_allclose(output1.as_tensor().cpu().numpy(),
                               negative_image_ref)
    # 3 channels
    output3.linear_transform(scale=-1, offset=1)
    np.testing.assert_allclose(output3.as_tensor().cpu().numpy(),
                               np.broadcast_to(negative_image_ref, (2, 3, 3)),
                               **TOL)

    # UInt8 -> UInt16: auto scale = 1
    output1 = input1.to(o3c.uint16)
    assert output1.dtype == o3c.uint16
    np.testing.assert_allclose(output1.as_tensor().cpu().numpy(), input_data,
                               **TOL)
    # 3 channels
    output3 = input3.to(o3c.uint16)
    np.testing.assert_allclose(output3.as_tensor().cpu().numpy(),
                               np.broadcast_to(input_data, (2, 3, 3)), **TOL)

    # Saturation to [0, 255]
    output1 = input1.linear_transform(scale=20, offset=-20)
    np.testing.assert_allclose(output1.as_tensor().cpu().numpy(), saturate_ref,
                               **TOL)
    # 3 channels
    output3 = input3.linear_transform(scale=20, offset=-20)
    np.testing.assert_allclose(output3.as_tensor().cpu().numpy(),
                               np.broadcast_to(saturate_ref, (2, 3, 3)), **TOL)


@pytest.mark.parametrize("device", list_devices())
def test_buffer_protocol_cpu(device):
    if device.get_type() == o3c.Device.DeviceType.CPU:
        # (rows, cols) -> (rows, cols, 1)
        src_t = np.array([[0, 1, 2], [3, 4, 5]], dtype=np.float32)
        im = Image(o3d.core.Tensor.from_numpy(src_t))
        dst_t = np.asarray(im)
        np.testing.assert_array_equal(src_t[..., None], dst_t)

        # Check that the memory is shared.
        dst_t[0, 0, 0] = 100
        new_dst_t = np.asarray(im)
        np.testing.assert_array_equal(dst_t, new_dst_t)

        # (rows, cols, channels) -> (rows, cols, channels)
        src_t = np.arange(18, dtype=np.float32).reshape((2, 3, 3))
        im = Image(o3d.core.Tensor.from_numpy(src_t))
        dst_t = np.asarray(im)
        np.testing.assert_array_equal(src_t, dst_t)

        # Check that the memory is shared.
        dst_t[0, 0, 0] = 100
        new_dst_t = np.asarray(im)
        np.testing.assert_array_equal(dst_t, new_dst_t)
    else:
        # (rows, cols) -> (rows, cols, 1)
        src_t = np.array([[0, 1, 2], [3, 4, 5]], dtype=np.float32)
        im = Image(o3d.core.Tensor.from_numpy(src_t))
        im = im.to(device=device)
        # Ideally we shall test exception if .cpu() is not called, but
        # pytest.raises() cannot catch this exception for some reason.
        dst_t = np.asarray(im.cpu())
        np.testing.assert_array_equal(src_t[..., None], dst_t)

        # (rows, cols, channels) -> (rows, cols, channels)
        src_t = np.arange(18, dtype=np.float32).reshape((2, 3, 3))
        im = Image(o3d.core.Tensor.from_numpy(src_t))
        im = im.to(device=device)
        dst_t = np.asarray(im.cpu())
        np.testing.assert_array_equal(src_t, dst_t)


@pytest.mark.parametrize("device", list_devices())
def test_pickle(device):
    img = Image(o3c.Tensor.ones((10, 10, 3), o3c.uint8, device))
    with tempfile.TemporaryDirectory() as temp_dir:
        file_name = f"{temp_dir}/img.pkl"
        pickle.dump(img, open(file_name, "wb"))
        img_load = pickle.load(open(file_name, "rb"))
        assert img_load.as_tensor().allclose(img.as_tensor())
        assert img_load.device == img.device and img_load.dtype == o3c.uint8