Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python SDK: document that we also accept colors in 0-1 floats #1740

Merged
merged 7 commits into from
Apr 4, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 9 additions & 8 deletions examples/python/arkitscenes/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from scipy.spatial.transform import Rotation as R
from tqdm import tqdm

Color = Tuple[float, float, float, float]

# hack for now since dataset does not provide orientation information, only known after initial visual inspection
ORIENTATION = {
"48458663": "landscape",
Expand All @@ -36,7 +38,7 @@ def load_json(js_path: Path) -> Dict[str, Any]:

def log_annotated_bboxes(
annotation: Dict[str, Any]
) -> Tuple[npt.NDArray[np.float64], List[str], List[Tuple[int, int, int, int]]]:
) -> Tuple[npt.NDArray[np.float64], List[str], List[Color]]:
"""
Logs annotated oriented bounding boxes to Rerun.

Expand All @@ -56,8 +58,7 @@ def log_annotated_bboxes(
# TODO(pablovela5620): Once #1581 or #1728 is resolved this can be removed
color_positions = np.linspace(0, 1, num_objects)
colormap = plt.cm.get_cmap("viridis")
color_array_float = [colormap(pos) for pos in color_positions]
color_list = [(int(r * 255), int(g * 255), int(b * 255), int(a * 255)) for r, g, b, a in color_array_float]
colors = [colormap(pos) for pos in color_positions]

for i, label_info in enumerate(annotation["data"]):
uid = label_info["uid"]
Expand All @@ -76,15 +77,15 @@ def log_annotated_bboxes(
position=transform,
rotation_q=rot.as_quat(),
label=label,
color=color_list[i],
color=colors[i],
timeless=True,
)

box3d = compute_box_3d(scale, transform, rotation)
bbox_list.append(box3d)
bbox_labels.append(label)
bboxes_3d = np.array(bbox_list)
return bboxes_3d, bbox_labels, color_list
return bboxes_3d, bbox_labels, colors


def compute_box_3d(
Expand Down Expand Up @@ -113,7 +114,7 @@ def compute_box_3d(


def log_line_segments(
entity_path: str, bboxes_2d_filtered: npt.NDArray[np.float64], color: Tuple[int, int, int, int], label: str
entity_path: str, bboxes_2d_filtered: npt.NDArray[np.float64], color: Color, label: str
) -> None:
"""
Generates line segments for each object's bounding box in 2d.
Expand Down Expand Up @@ -239,7 +240,7 @@ def log_camera(
entity_id: str,
bboxes: npt.NDArray[np.float64],
bbox_labels: List[str],
color_list: List[Tuple[int, int, int, int]],
colors: List[Color],
) -> None:
"""Logs camera transform and 3D bounding boxes in the image frame."""
w, h, fx, fy, cx, cy = np.loadtxt(intri_path)
Expand All @@ -253,7 +254,7 @@ def log_camera(
rr.log_cleared(f"{entity_id}/bbox-2d-segments", recursive=True)
# Log line segments for each bounding box in the image
for i, (label, bbox_2d) in enumerate(zip(bbox_labels, bboxes_2d)):
log_line_segments(f"{entity_id}/bbox-2d-segments/{label}", bbox_2d.reshape(-1, 2), color_list[i], label)
log_line_segments(f"{entity_id}/bbox-2d-segments/{label}", bbox_2d.reshape(-1, 2), colors[i], label)

rr.log_rigid3(
# pathlib makes it easy to get the parent, but log_rigid requires a string
Expand Down
13 changes: 10 additions & 3 deletions rerun_py/rerun_sdk/rerun/log/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import numpy.typing as npt

from rerun import bindings
from rerun.color_conversion import linear_to_gamma_u8_pixel

__all__ = [
"annotation",
Expand Down Expand Up @@ -43,7 +42,14 @@ def _to_sequence(array: Optional[npt.ArrayLike]) -> Optional[Sequence[float]]:


def _normalize_colors(colors: Optional[Union[Color, Colors]] = None) -> npt.NDArray[np.uint8]:
"""Normalize flexible colors arrays."""
"""
Normalize flexible colors arrays.

Float colors are assumed to be in 0-1 gamma sRGB space.
All other colors are assumed to be in 0-255 gamma sRGB space.

If there is an alpha, we assume it is in linear space, and separate (NOT pre-multiplied).
"""
if colors is None:
# An empty array represents no colors.
return np.array((), dtype=np.uint8)
Expand All @@ -52,7 +58,8 @@ def _normalize_colors(colors: Optional[Union[Color, Colors]] = None) -> npt.NDAr

# Rust expects colors in 0-255 uint8
if colors_array.dtype.type in [np.float32, np.float64]:
return linear_to_gamma_u8_pixel(linear=colors_array)
# Assume gamma-space colors
return np.require(np.round(colors_array * 255.0), np.uint8)

return np.require(colors_array, np.uint8)

Expand Down
2 changes: 1 addition & 1 deletion rerun_py/rerun_sdk/rerun/log/annotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def log_annotation_context(

Each ClassDescription must include an annotation info with an id, which will
be used for matching the class and may optionally include a label and color.
Colors should either be in 0-255 gamma space or in 0-1 linear space. Colors
Colors should either be in 0-255 gamma space or in 0-1 gamma space. Colors
can be RGB or RGBA.

These can either be specified verbosely as:
Expand Down
8 changes: 4 additions & 4 deletions rerun_py/rerun_sdk/rerun/log/arrow.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, Optional, Sequence
from typing import Any, Dict, Optional

import numpy as np
import numpy.typing as npt
Expand All @@ -9,7 +9,7 @@
from rerun.components.instance import InstanceArray
from rerun.components.label import LabelArray
from rerun.components.radius import RadiusArray
from rerun.log import _normalize_colors, _normalize_radii
from rerun.log import Color, _normalize_colors, _normalize_radii
from rerun.log.extension_components import _add_extension_components
from rerun.log.log_decorator import log_decorator

Expand All @@ -24,7 +24,7 @@ def log_arrow(
origin: Optional[npt.ArrayLike],
vector: Optional[npt.ArrayLike] = None,
*,
color: Optional[Sequence[int]] = None,
color: Optional[Color] = None,
label: Optional[str] = None,
width_scale: Optional[float] = None,
ext: Optional[Dict[str, Any]] = None,
Expand All @@ -48,7 +48,7 @@ def log_arrow(
vector
The vector along which the arrow will be drawn.
color
An optional RGB or RGBA triplet in 0-255 sRGB.
Optional RGB or RGBA in sRGB gamma-space as either 0-1 floats or 0-255 integers, with separate alpha.
label
An optional text to show beside the arrow.
width_scale
Expand Down
8 changes: 4 additions & 4 deletions rerun_py/rerun_sdk/rerun/log/bounding_box.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, Optional, Sequence
from typing import Any, Dict, Optional

import numpy as np
import numpy.typing as npt
Expand All @@ -12,7 +12,7 @@
from rerun.components.quaternion import QuaternionArray
from rerun.components.radius import RadiusArray
from rerun.components.vec import Vec3DArray
from rerun.log import _normalize_colors, _normalize_ids, _normalize_radii
from rerun.log import Color, _normalize_colors, _normalize_ids, _normalize_radii
from rerun.log.extension_components import _add_extension_components
from rerun.log.log_decorator import log_decorator

Expand All @@ -27,7 +27,7 @@ def log_obb(
half_size: Optional[npt.ArrayLike],
position: Optional[npt.ArrayLike] = None,
rotation_q: Optional[npt.ArrayLike] = None,
color: Optional[Sequence[int]] = None,
color: Optional[Color] = None,
stroke_width: Optional[float] = None,
label: Optional[str] = None,
class_id: Optional[int] = None,
Expand All @@ -54,7 +54,7 @@ def log_obb(
rotation_q:
Optional array with quaternion coordinates [x, y, z, w] for the rotation from model to world space.
color:
Optional RGB or RGBA triplet in 0-255 sRGB.
Optional RGB or RGBA in sRGB gamma-space as either 0-1 floats or 0-255 integers, with separate alpha.
stroke_width:
Optional width of the line edges.
label:
Expand Down
14 changes: 7 additions & 7 deletions rerun_py/rerun_sdk/rerun/log/lines.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, Optional, Sequence
from typing import Any, Dict, Optional

import numpy as np
import numpy.typing as npt
Expand All @@ -9,7 +9,7 @@
from rerun.components.instance import InstanceArray
from rerun.components.linestrip import LineStrip2DArray, LineStrip3DArray
from rerun.components.radius import RadiusArray
from rerun.log import _normalize_colors, _normalize_radii
from rerun.log import Color, _normalize_colors, _normalize_radii
from rerun.log.extension_components import _add_extension_components
from rerun.log.log_decorator import log_decorator

Expand All @@ -26,7 +26,7 @@ def log_path(
positions: Optional[npt.ArrayLike],
*,
stroke_width: Optional[float] = None,
color: Optional[Sequence[int]] = None,
color: Optional[Color] = None,
ext: Optional[Dict[str, Any]] = None,
timeless: bool = False,
) -> None:
Expand All @@ -39,7 +39,7 @@ def log_line_strip(
positions: Optional[npt.ArrayLike],
*,
stroke_width: Optional[float] = None,
color: Optional[Sequence[int]] = None,
color: Optional[Color] = None,
ext: Optional[Dict[str, Any]] = None,
timeless: bool = False,
) -> None:
Expand All @@ -65,7 +65,7 @@ def log_line_strip(
stroke_width:
Optional width of the line.
color:
Optional RGB or RGBA triplet in 0-255 sRGB.
Optional RGB or RGBA in sRGB gamma-space as either 0-1 floats or 0-255 integers, with separate alpha.
ext:
Optional dictionary of extension components. See [rerun.log_extension_components][]
timeless:
Expand Down Expand Up @@ -114,7 +114,7 @@ def log_line_segments(
positions: npt.ArrayLike,
*,
stroke_width: Optional[float] = None,
color: Optional[Sequence[int]] = None,
color: Optional[Color] = None,
ext: Optional[Dict[str, Any]] = None,
timeless: bool = False,
) -> None:
Expand All @@ -139,7 +139,7 @@ def log_line_segments(
stroke_width:
Optional width of the line.
color:
Optional RGB or RGBA triplet in 0-255 sRGB.
Optional RGB or RGBA in sRGB gamma-space as either 0-1 floats or 0-255 integers, with separate alpha.
ext:
Optional dictionary of extension components. See [rerun.log_extension_components][]
timeless:
Expand Down
3 changes: 2 additions & 1 deletion rerun_py/rerun_sdk/rerun/log/mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ def log_mesh(
albedo_factor:
Optional color multiplier of the mesh using RGB or unmuliplied RGBA in linear 0-1 space.
vertex_colors:
Optional array of RGB(a) vertex colors
Optional array of RGB(A) vertex colors, in sRGB gamma space, either as 0-1 floats or 0-255 integers.
If specified, the alpha is considered separate (unmultiplied).
timeless:
If true, the mesh will be timeless (default: False)

Expand Down
6 changes: 4 additions & 2 deletions rerun_py/rerun_sdk/rerun/log/points.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def log_point(
position: Optional[npt.ArrayLike] = None,
*,
radius: Optional[float] = None,
color: Optional[Sequence[int]] = None,
color: Optional[Color] = None,
label: Optional[str] = None,
class_id: Optional[int] = None,
keypoint_id: Optional[int] = None,
Expand Down Expand Up @@ -66,7 +66,7 @@ def log_point(
radius:
Optional radius (make it a sphere).
color:
Optional color of the point.
Optional RGB or RGBA in sRGB gamma-space as either 0-1 floats or 0-255 integers, with separate alpha.
label:
Optional text to show with the point.
class_id:
Expand Down Expand Up @@ -169,6 +169,8 @@ def log_points(
Unique numeric id that shows up when you hover or select the point.
colors:
Optional colors of the points.
The colors are interpreted as RGB or RGBA in sRGB gamma-space,
as either 0-1 floats or 0-255 integers, with separate alpha.
radii:
Optional radii (make it a sphere).
labels:
Expand Down
6 changes: 3 additions & 3 deletions rerun_py/rerun_sdk/rerun/log/rects.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def log_rect(
rect: Optional[npt.ArrayLike],
*,
rect_format: RectFormat = RectFormat.XYWH,
color: Optional[Sequence[int]] = None,
color: Optional[Color] = None,
label: Optional[str] = None,
class_id: Optional[int] = None,
ext: Optional[Dict[str, Any]] = None,
Expand All @@ -52,7 +52,7 @@ def log_rect(
rect_format:
how to interpret the `rect` argument
color:
Optional RGB or RGBA triplet in 0-255 sRGB.
Optional RGB or RGBA in sRGB gamma-space as either 0-1 floats or 0-255 integers, with separate alpha.
label:
Optional text to show inside the rectangle.
class_id:
Expand Down Expand Up @@ -139,7 +139,7 @@ def log_rects(
identifiers:
Unique numeric id that shows up when you hover or select the point.
colors:
Optional per-rectangle RGB or RGBA triplet in 0-255 sRGB.
Optional per-rectangle gamma-space RGB or RGBA as 0-1 floats or 0-255 integers.
labels:
Optional per-rectangle text to show inside the rectangle.
class_ids:
Expand Down
10 changes: 5 additions & 5 deletions rerun_py/rerun_sdk/rerun/log/scalar.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, Optional, Sequence
from typing import Any, Dict, Optional

import numpy as np

Expand All @@ -8,7 +8,7 @@
from rerun.components.label import LabelArray
from rerun.components.radius import RadiusArray
from rerun.components.scalar import ScalarArray, ScalarPlotPropsArray
from rerun.log import _normalize_colors
from rerun.log import Color, _normalize_colors
from rerun.log.extension_components import _add_extension_components
from rerun.log.log_decorator import log_decorator

Expand All @@ -22,7 +22,7 @@ def log_scalar(
entity_path: str,
scalar: float,
label: Optional[str] = None,
color: Optional[Sequence[int]] = None,
color: Optional[Color] = None,
radius: Optional[float] = None,
scattered: Optional[bool] = None,
ext: Optional[Dict[str, Any]] = None,
Expand Down Expand Up @@ -81,7 +81,7 @@ def log_scalar(
line will be named after the entity path. The plot itself is named after
the space it's in.
color:
An optional color in the form of a RGB or RGBA triplet in 0-255 sRGB.
Optional RGB or RGBA in sRGB gamma-space as either 0-1 floats or 0-255 integers, with separate alpha.

If left unspecified, a pseudo-random color will be used instead. That
same color will apply to all points residing in the same entity path
Expand Down Expand Up @@ -121,7 +121,7 @@ def log_scalar(
instanced["rerun.label"] = LabelArray.new([label])

if color:
colors = _normalize_colors(np.array([color]))
colors = _normalize_colors([color])
instanced["rerun.colorrgba"] = ColorRGBAArray.from_numpy(colors)

if radius:
Expand Down
8 changes: 4 additions & 4 deletions rerun_py/rerun_sdk/rerun/log/text.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import logging
from typing import Any, Dict, Final, Optional, Sequence
from typing import Any, Dict, Final, Optional

# Fully qualified to avoid circular import
import rerun.log.extension_components
from rerun import bindings
from rerun.components.color import ColorRGBAArray
from rerun.components.instance import InstanceArray
from rerun.components.text_entry import TextEntryArray
from rerun.log import _normalize_colors
from rerun.log import Color, _normalize_colors
from rerun.log.log_decorator import log_decorator
from rerun.log.text_internal import LogLevel

Expand Down Expand Up @@ -71,7 +71,7 @@ def log_text_entry(
text: str,
*,
level: Optional[str] = LogLevel.INFO,
color: Optional[Sequence[int]] = None,
color: Optional[Color] = None,
ext: Optional[Dict[str, Any]] = None,
timeless: bool = False,
) -> None:
Expand All @@ -89,7 +89,7 @@ def log_text_entry(
be an arbitrary string, but it's recommended to use one of the constants
from [LogLevel][rerun.log.text.LogLevel]
color:
Optional RGB or RGBA triplet in 0-255 sRGB.
Optional RGB or RGBA in sRGB gamma-space as either 0-1 floats or 0-255 integers, with separate alpha.
ext:
Optional dictionary of extension components. See [rerun.log_extension_components][]
timeless:
Expand Down