Fade effect, and prep for more advanced line corretion using Shapely

This commit is contained in:
Ruben van de Ven 2025-04-29 16:58:21 +02:00
parent 73671ddd69
commit b5a6dfbf5a
8 changed files with 601 additions and 159 deletions

View file

@ -23,7 +23,8 @@ dependencies = [
"bytetracker", "bytetracker",
"jsonlines>=4.0.0,<5", "jsonlines>=4.0.0,<5",
"tensorboardx>=2.6.2.2,<3", "tensorboardx>=2.6.2.2,<3",
"shapely>=1,<2", "shapely>=2.1",
#"shapely>=1,<2",
"baumer-neoapi", "baumer-neoapi",
"qrcode~=8.0", "qrcode~=8.0",
"pyusb>=1.3.1,<2", "pyusb>=1.3.1,<2",

435
test_path_transforms.ipynb Normal file

File diff suppressed because one or more lines are too long

View file

@ -65,7 +65,7 @@ class FrameEmitter:
def emit_video(self, timer_counter): def emit_video(self, timer_counter):
i = 0 i = 0
source = get_video_source(self.video_srcs, self.config.camera, int(self.config.video_offset), self.config.video_end, self.config.video_loop) source = get_video_source(self.video_srcs, self.config.camera, int(self.config.video_offset or 0), self.config.video_end, self.config.video_loop)
for i, img in enumerate(source): for i, img in enumerate(source):
with timer_counter.get_lock(): with timer_counter.get_lock():

67
trap/lines.py Normal file
View file

@ -0,0 +1,67 @@
from __future__ import annotations
from dataclasses import dataclass
from enum import Enum
from typing import List, Tuple
from simplification.cutil import simplify_coords_idx, simplify_coords_vw_idx
"""
See [notebook](../test_path_transforms.ipynb) for examples
"""
RenderablePosition = Tuple[float,float]
@dataclass
class SrgbaColor():
red: float
green: float
blue: float
alpha: float
def with_alpha(self, alpha: float) -> SrgbaColor:
return SrgbaColor(self.red, self.green, self.blue, alpha)
def as_faded(self, alpha: float) -> SrgbaColor:
return SrgbaColor(self.red, self.green, self.blue, self.alpha * alpha)
@dataclass
class RenderablePoint():
position: RenderablePosition
color: SrgbaColor
@classmethod
def from_list(cls, l: List[float, float], color: SrgbaColor) -> RenderablePoint:
return cls([float(l[0]), float(l[1])], color)
SIMPLIFY_FACTOR_RDP = .05 # smaller is more detailed
SIMPLIFY_FACTOR_VW = 10
class SimplifyMethod(Enum):
RDP = 1 #' RamerDouglasPeucker'
VW = 2 # Visvalingam-Whyatt
@dataclass
class RenderableLine():
points: List[RenderablePoint]
def as_simplified(self, method: SimplifyMethod = SimplifyMethod.RDP):
linestring = [p.position for p in self.points]
if method == SimplifyMethod.RDP:
indexes = simplify_coords_idx(linestring, SIMPLIFY_FACTOR_RDP)
elif method == SimplifyMethod.VW:
indexes = simplify_coords_vw_idx(linestring, SIMPLIFY_FACTOR_VW)
points = [self.points[i] for i in indexes]
return RenderableLine(points)
@dataclass
class RenderableLines():
lines: List[RenderableLine]
def as_simplified(self, method: SimplifyMethod = SimplifyMethod.RDP):
"""Wraps RenderableLine simplification"""
return RenderableLines(
[line.as_simplified(method) for line in self.lines]
)

View file

@ -51,3 +51,4 @@ class Node():
def start(cls, config: Namespace, is_running: BaseEvent, timer_counter: Optional[Timer]): def start(cls, config: Namespace, is_running: BaseEvent, timer_counter: Optional[Timer]):
instance = cls(config, is_running, timer_counter) instance = cls(config, is_running, timer_counter)
instance.run() instance.run()
instance.logger.info("Stopping")

View file

@ -5,6 +5,7 @@ from dataclasses import dataclass
from enum import Enum from enum import Enum
import json import json
import logging import logging
import pickle
import time import time
from typing import Dict, List, Optional, Tuple from typing import Dict, List, Optional, Tuple
import numpy as np import numpy as np
@ -12,13 +13,13 @@ from statemachine import Event, State, StateMachine
from statemachine.exceptions import TransitionNotAllowed from statemachine.exceptions import TransitionNotAllowed
import zmq import zmq
from simplification.cutil import simplify_coords_idx, simplify_coords_vw_idx
from sgan.sgan import data from sgan.sgan import data
from trap import shapes from trap import shapes
from trap.base import DataclassJSONEncoder, Frame, Track from trap.base import DataclassJSONEncoder, Frame, Track
from trap.counter import CounterSender from trap.counter import CounterSender
from trap.laser_renderer import rotateMatrix from trap.laser_renderer import rotateMatrix
from trap.lines import RenderableLine, RenderableLines, RenderablePoint, SrgbaColor
from trap.node import Node from trap.node import Node
from trap.timer import Timer from trap.timer import Timer
from trap.utils import exponentialDecay, relativePointToPolar, relativePolarToPoint from trap.utils import exponentialDecay, relativePointToPolar, relativePolarToPoint
@ -33,6 +34,19 @@ class ScenarioScene(Enum):
LOST = -1 LOST = -1
LOST_FADEOUT = 3 LOST_FADEOUT = 3
PREDICTION_INTERVAL: float|None = 1
PREDICTION_FADE_IN: float = 3
PREDICTION_FADE_SLOPE: float = -10
PREDICTION_FADE_AFTER_DURATION: float = 10 # seconds
PREDICTION_END_FADE = 2 #frames
# TRACK_MAX_POINTS = 100
TRACK_FADE_AFTER_DURATION = 10. # seconds
TRACK_END_FADE = 50 # points
TRACK_FADE_ASSUME_FPS = 12
# Don't render the first n points of the prediction,
# helps to avoid jitter in the line transition
PREDICTION_OFFSET = int(TRACK_FADE_ASSUME_FPS * PREDICTION_INTERVAL * .8)
class TrackScenario(StateMachine): class TrackScenario(StateMachine):
detected = State(initial=True) detected = State(initial=True)
@ -70,7 +84,7 @@ class TrackScenario(StateMachine):
def prediction_is_stale(self, track: Track): def prediction_is_stale(self, track: Track):
# TODO use displacement instead of time # TODO use displacement instead of time
return bool(self.prediction_track and self.prediction_track.created_at < (time.perf_counter() - 2)) return bool(self.prediction_track and self.prediction_track.created_at < (time.time() - 2))
def prediction_is_playing(self, Track): def prediction_is_playing(self, Track):
return False return False
@ -99,7 +113,7 @@ class TrackScenario(StateMachine):
if not self.first_prediction_track: if not self.first_prediction_track:
self.first_prediction_track = track self.first_prediction_track = track
if self.prediction_track and (track.created_at - self.prediction_track.created_at) < .7: if PREDICTION_INTERVAL is not None and self.prediction_track and (track.created_at - self.prediction_track.created_at) < PREDICTION_INTERVAL:
# just drop tracks if the predictions come to quick # just drop tracks if the predictions come to quick
return return
@ -236,7 +250,7 @@ class DrawnScenario(TrackScenario):
# TODO: this should be done in polar space starting from origin (i.e. self.drawn_posision[-1]) # TODO: this should be done in polar space starting from origin (i.e. self.drawn_posision[-1])
decay = max(3, (18/i) if i else 10) # points further away move with more delay decay = max(3, (18/i) if i else 10) # points further away move with more delay
decay = 16 decay = 16
origin = self.drawn_positions[-1] origin = self.drawn_positions[-1]
drawn_r, drawn_angle = relativePointToPolar( origin, drawn_prediction[i]) drawn_r, drawn_angle = relativePointToPolar( origin, drawn_prediction[i])
pred_r, pred_angle = relativePointToPolar(origin, self.prediction_track.predictions[a][i+prediction_offset]) pred_r, pred_angle = relativePointToPolar(origin, self.prediction_track.predictions[a][i+prediction_offset])
r = exponentialDecay(drawn_r, pred_r, decay, dt) r = exponentialDecay(drawn_r, pred_r, decay, dt)
@ -253,17 +267,43 @@ class DrawnScenario(TrackScenario):
# if len(self.pred_coords) > len(self.drawn_predictions): # if len(self.pred_coords) > len(self.drawn_predictions):
# self.drawn_predictions.extend(self.pred_coords[len(self.drawn_predictions):]) # self.drawn_predictions.extend(self.pred_coords[len(self.drawn_predictions):])
def to_renderable_lines(self) -> RenderableLines: def to_renderable_lines(self) -> RenderableLines:
track_age = time.time() - self._track.created_at
drawable_points, alphas = points_fade_out_alpha_mask(self.drawn_positions, track_age, TRACK_FADE_AFTER_DURATION, TRACK_END_FADE)
# track_age_in_frames = int(track_age * TRACK_FADE_ASSUME_FPS)
# track_max_points = TRACK_FADE_AFTER_DURATION * TRACK_FADE_ASSUME_FPS - track_age_in_frames
lines: List[RenderableLine] = [] lines: List[RenderableLine] = []
color = SrgbaColor(1.,0.,0.,1.-self.lost_factor()) color = SrgbaColor(1.,0.,0.,1.-self.lost_factor())
# positions = [RenderablePosition.from_list(pos) for pos in self.drawn_positions]
points = [RenderablePoint(pos, color) for pos in self.drawn_positions[::4]] points = [RenderablePoint(pos, color.as_faded(a)) for pos, a in zip(drawable_points, alphas)]
lines.append(RenderableLine(points)) lines.append(RenderableLine(points))
if len(self.drawn_predictions): if len(self.drawn_predictions):
color = SrgbaColor(0.,0.5,0.,1.-self.lost_factor()) color = SrgbaColor(0.,1,0.,1.-self.lost_factor())
prediction_track_age = time.time() - self.first_prediction_track.created_at
t_factor = prediction_track_age / PREDICTION_FADE_IN
# positions = [RenderablePosition.from_list(pos) for pos in self.drawn_positions] # positions = [RenderablePosition.from_list(pos) for pos in self.drawn_positions]
points = [RenderablePoint(pos, color) for pos in self.drawn_predictions[0]] for drawn_prediction in self.drawn_predictions:
lines.append(RenderableLine(points))
# drawn_prediction, alphas1 = points_fade_out_alpha_mask(drawn_prediction, prediction_track_age, TRACK_FADE_AFTER_DURATION, TRACK_END_FADE, no_frame_max=True)
gradient = np.linspace(0, PREDICTION_FADE_SLOPE, len(drawn_prediction))
alphas2 = np.clip(gradient + t_factor * (-1*PREDICTION_FADE_SLOPE), 0, 1)
# print(alphas)
# colors = [color.with_alpha(np.clip(t_factor*3-(p_index/len(drawn_prediction)), 0, 1)) for p_index in range(len(drawn_prediction))]
# colors = [color.with_alpha(np.clip(t_factor*2-(p_index/len(drawn_prediction)), 0, 1)) for p_index in range(len(drawn_prediction))]
# apply both fade in and fade out mask:
colors = [color.as_faded(a2) for a2 in alphas2]
# colors = [color.as_faded(a1*a2) for a1, a2 in zip(alphas1, alphas2)]
points = [RenderablePoint(pos, pos_color) for pos, pos_color in zip(drawn_prediction[PREDICTION_OFFSET:], colors[PREDICTION_OFFSET:])]
lines.append(RenderableLine(points))
# # print(self.current_state) # # print(self.current_state)
# if self.current_state is self.first_prediction or self.current_state is self.corrected_prediction: # if self.current_state is self.first_prediction or self.current_state is self.corrected_prediction:
@ -315,8 +355,33 @@ class DrawnScenario(TrackScenario):
def points_fade_out_alpha_mask(positions: List, track_age_seconds: float, fade_after_duration: float, fade_frames: int, no_frame_max=False):
track_age_in_frames = int(track_age_seconds * TRACK_FADE_ASSUME_FPS)
if not no_frame_max:
track_max_points = int(fade_after_duration * TRACK_FADE_ASSUME_FPS) - track_age_in_frames
else:
if track_age_seconds < fade_after_duration:
track_max_points = len(positions) #+ fade_frames
else:
FADE_DURATION = 2
t_fade = max(0, track_age_seconds - fade_after_duration) / FADE_DURATION
track_max_points = int(t_fade * len(positions) / FADE_DURATION)
drawable_points = positions[-track_max_points:]
alphas = []
for i, point in enumerate(drawable_points):
reverse_i = len(drawable_points) - i
fade_i = reverse_i - (track_max_points - fade_frames) # -90
fade_i /= fade_frames # / 10
fade_i = np.clip(fade_i, 0, 1)
alpha = 1 - fade_i
if alpha > 0:
alphas.append(alpha)
return drawable_points, alphas
# drawn_pred_history # drawn_pred_history
# drawn_predictions # drawn_predictions
@ -331,58 +396,6 @@ class DrawnScenario(TrackScenario):
# return cls(x = float(l[0]), y=float(l[1])) # return cls(x = float(l[0]), y=float(l[1]))
# TODO)) Or Shapely point? # TODO)) Or Shapely point?
RenderablePosition = Tuple[float,float]
@dataclass
class SrgbaColor():
red: float
green: float
blue: float
alpha: float
def with_alpha(self, alpha: float) -> SrgbaColor:
return SrgbaColor(self.red, self.green, self.blue, alpha)
@dataclass
class RenderablePoint():
position: RenderablePosition
color: SrgbaColor
@classmethod
def from_list(cls, l: List[float, float], color: SrgbaColor) -> RenderablePoint:
return cls([float(l[0]), float(l[1])], color)
SIMPLIFY_FACTOR_RDP = .5
SIMPLIFY_FACTOR_VW = 10
class SimplifyMethod(Enum):
RDP = 1 #' RamerDouglasPeucker'
VW = 2 # Visvalingam-Whyatt
@dataclass
class RenderableLine():
points: List[RenderablePoint]
def as_simplified(self, method: SimplifyMethod = SimplifyMethod.RDP):
linestring = [p.position for p in self.points]
if method == SimplifyMethod.RDP:
indexes = simplify_coords_idx(linestring, SIMPLIFY_FACTOR_RDP)
elif method == SimplifyMethod.VW:
indexes = simplify_coords_vw_idx(linestring, SIMPLIFY_FACTOR_VW)
points = [self.points[i] for i in indexes]
return RenderableLine(points)
@dataclass
class RenderableLines():
lines: List[RenderableLine]
def as_simplified(self, method: SimplifyMethod = SimplifyMethod.RDP):
"""Wraps RenderableLine simplification"""
return RenderableLines(
[line.as_simplified(method) for line in self.lines]
)
class Stage(Node): class Stage(Node):
""" """
@ -460,7 +473,9 @@ class Stage(Node):
# print(lines) # print(lines)
rl = RenderableLines(lines) rl = RenderableLines(lines)
rl = rl.as_simplified() # with open('/tmp/lines.pcl', 'wb') as fp:
# pickle.dump(rl, fp)
rl = rl.as_simplified() # or segmentise (see shapely)
self.counter.set("stage.lines", len(lines)) self.counter.set("stage.lines", len(lines))
self.stage_sock.send_json(rl, cls=DataclassJSONEncoder) self.stage_sock.send_json(rl, cls=DataclassJSONEncoder)

View file

@ -29,6 +29,8 @@ def inv_lerp(a: float, b: float, v: float) -> float:
return (v - a) / (b - a) return (v - a) / (b - a)
def exponentialDecay(a, b, decay, dt): def exponentialDecay(a, b, decay, dt):
"""Exponential decay as alternative to Lerp """Exponential decay as alternative to Lerp
Introduced by Freya Holmér: https://www.youtube.com/watch?v=LSNQuFEDOyQ Introduced by Freya Holmér: https://www.youtube.com/watch?v=LSNQuFEDOyQ

109
uv.lock
View file

@ -265,15 +265,6 @@ dependencies = [
{ name = "scipy" }, { name = "scipy" },
] ]
[[package]]
name = "cachetools"
version = "5.5.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/6c/81/3747dad6b14fa2cf53fcf10548cf5aea6913e96fab41a3c198676f8948a5/cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4", size = 28380 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/72/76/20fa66124dbe6be5cafeb312ece67de6b61dd91a0247d1ea13db4ebb33c2/cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a", size = 10080 },
]
[[package]] [[package]]
name = "certifi" name = "certifi"
version = "2025.1.31" version = "2025.1.31"
@ -415,18 +406,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604 }, { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604 },
] ]
[[package]]
name = "descartes"
version = "1.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "matplotlib" },
]
sdist = { url = "https://files.pythonhosted.org/packages/1d/6f/81735a30432b74f41db6754dd13869021ccfed3088d1cf7a6cfc0af9ac49/descartes-1.1.0.tar.gz", hash = "sha256:135a502146af5ed6ff359975e2ebc5fa4b71b5432c355c2cafdc6dea1337035b", size = 3525 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e5/b6/1ed2eb03989ae574584664985367ba70cd9cf8b32ee8cad0e8aaeac819f3/descartes-1.1.0-py3-none-any.whl", hash = "sha256:4c62dc41109689d03e4b35de0a2bcbdeeb81047badc607c4415d5c753bd683af", size = 5804 },
]
[[package]] [[package]]
name = "dill" name = "dill"
version = "0.3.9" version = "0.3.9"
@ -523,15 +502,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215 }, { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215 },
] ]
[[package]]
name = "fire"
version = "0.7.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "termcolor" },
]
sdist = { url = "https://files.pythonhosted.org/packages/6b/b6/82c7e601d6d3c3278c40b7bd35e17e82aa227f050aa9f66cb7b7fce29471/fire-0.7.0.tar.gz", hash = "sha256:961550f07936eaf65ad1dc8360f2b2bf8408fad46abbfa4d2a3794f8d2a95cdf", size = 87189 }
[[package]] [[package]]
name = "fonttools" name = "fonttools"
version = "4.56.0" version = "4.56.0"
@ -1374,29 +1344,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/19/77/538f202862b9183f54108557bfda67e17603fc560c384559e769321c9d92/numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5", size = 15808905 }, { url = "https://files.pythonhosted.org/packages/19/77/538f202862b9183f54108557bfda67e17603fc560c384559e769321c9d92/numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5", size = 15808905 },
] ]
[[package]]
name = "nuscenes-devkit"
version = "1.1.11"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cachetools" },
{ name = "descartes" },
{ name = "fire" },
{ name = "matplotlib" },
{ name = "numpy" },
{ name = "opencv-python" },
{ name = "pillow" },
{ name = "pycocotools" },
{ name = "pyquaternion" },
{ name = "scikit-learn" },
{ name = "scipy" },
{ name = "shapely" },
{ name = "tqdm" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/b0/06/9029f796dcf7854f0681f11ae81fe42542fb15e02830f6b4239749f59739/nuscenes_devkit-1.1.11-py3-none-any.whl", hash = "sha256:f8ab21957b86590bdb23931de70d569dc0184142e5a4c83ec22a3493e99640d6", size = 313058 },
]
[[package]] [[package]]
name = "opencv-python" name = "opencv-python"
version = "4.10.0.84" version = "4.10.0.84"
@ -1663,25 +1610,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5", size = 22335 }, { url = "https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5", size = 22335 },
] ]
[[package]]
name = "pycocotools"
version = "2.0.8"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "matplotlib" },
{ name = "numpy" },
]
sdist = { url = "https://files.pythonhosted.org/packages/6b/1a/cdfce175d663568215b3a6b6170ad2a526932cc1021dffabda56a5c3f189/pycocotools-2.0.8.tar.gz", hash = "sha256:8f2bcedb786ba26c367a3680f9c4eb5b2ad9dccb2b34eaeb205e0a021e1dfb8d", size = 24993 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e1/03/8738c457ca04aed97f79781827b20862e78262da7ccc8062bcc6d6e857e2/pycocotools-2.0.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9a66886f45b04cee1ff0492e9f5e25d430d8aa3eb63e63c4ebc620945caa11b9", size = 162301 },
{ url = "https://files.pythonhosted.org/packages/ad/0a/bcd4592a85896a4281bb8ec5dd034ce12d82bb26b6e73e73b3c435377db1/pycocotools-2.0.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:257130b65b7b0f122ce1ed62942867ca9789e56a68109682796cc85c9770c74a", size = 410644 },
{ url = "https://files.pythonhosted.org/packages/6a/03/6c0bf810a5df7876caaf11f5b113e7ffd4b2fa9767d360489c6fdcefe8e5/pycocotools-2.0.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:663c14cd471913aabecb17ddb52b3b254a65dcaba26ccfea408c52c75cc3862c", size = 427769 },
{ url = "https://files.pythonhosted.org/packages/03/76/587579abcf3bab2b5a9b89ee28e78bef3df3198d724a4980b0875f69586b/pycocotools-2.0.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:35a6ef931448632efe1c83eb2ac3c37c53b3c080a5432bc6ff1858944a603a2d", size = 408920 },
{ url = "https://files.pythonhosted.org/packages/6d/d2/57421216b31920eb942bd8a81cead5e9b42dfd433e15d682cd7e156b6f84/pycocotools-2.0.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e7b4ee8b15539d6f789857faefe7d3eef81755f7b17f60903798524e4f321a5c", size = 426178 },
{ url = "https://files.pythonhosted.org/packages/8d/06/b9bdedfdcbf2fb5ba55252f1a5ff5e8e02ae204fe392f7b4f5babbc14a2a/pycocotools-2.0.8-cp310-cp310-win_amd64.whl", hash = "sha256:889edd2dbf61f4d2fe77c2e8e5608476903d1911d2ed00f9911354eff23f2423", size = 84484 },
{ url = "https://files.pythonhosted.org/packages/05/90/52de34f2f032e3de957c953fd1d4a9025175622714e5023ba4d6a9a96ece/pycocotools-2.0.8-cp310-cp310-win_arm64.whl", hash = "sha256:52e06a833fad735485cad5c1f8fe40e2b586261b2856806b5d6923b0b5a3c971", size = 70968 },
]
[[package]] [[package]]
name = "pycparser" name = "pycparser"
version = "2.22" version = "2.22"
@ -2154,18 +2082,21 @@ wheels = [
[[package]] [[package]]
name = "shapely" name = "shapely"
version = "1.8.5.post1" version = "2.1.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/92/2e/a8bbe3c6b414c3c61c4b639ab16d5b1f9c4c4095817d417b503413e613c0/Shapely-1.8.5.post1.tar.gz", hash = "sha256:ef3be705c3eac282a28058e6c6e5503419b250f482320df2172abcbea642c831", size = 200928 } dependencies = [
{ name = "numpy" },
]
sdist = { url = "https://files.pythonhosted.org/packages/fb/fe/3b0d2f828ffaceadcdcb51b75b9c62d98e62dd95ce575278de35f24a1c20/shapely-2.1.0.tar.gz", hash = "sha256:2cbe90e86fa8fc3ca8af6ffb00a77b246b918c7cf28677b7c21489b678f6b02e", size = 313617 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/7a/6f/9f67f1693087319e3ab45e2fbbc2bf1e81c47413c75a3ffff06a90f6bf44/Shapely-1.8.5.post1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d048f93e42ba578b82758c15d8ae037d08e69d91d9872bca5a1895b118f4e2b0", size = 2174486 }, { url = "https://files.pythonhosted.org/packages/98/97/7027722bec6fba6fbfdb36ff987bc368f6cd01ff91d3815bce93439ef3f5/shapely-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d3e5c5e3864d4dc431dd85a8e5137ebd39c8ac287b009d3fa80a07017b29c940", size = 1826440 },
{ url = "https://files.pythonhosted.org/packages/40/c2/f4265ebd6f2947f9d391676f998a8fad293ca91ba8704908527428913e9d/Shapely-1.8.5.post1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99ab0ddc05e44acabdbe657c599fdb9b2d82e86c5493bdae216c0c4018a82dee", size = 1206762 }, { url = "https://files.pythonhosted.org/packages/7e/de/d2ee50a66fcff3786a00b59b99b5bf3a7ec7bb1805e1c409a1c9c1817749/shapely-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6eea89b16f5f3a064659126455d23fa3066bc3d6cd385c35214f06bf5871aa6", size = 1627651 },
{ url = "https://files.pythonhosted.org/packages/34/30/5704c57904ea600ef041b960753cd5fc78a315210ae2b927a11d3aba2d6c/Shapely-1.8.5.post1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:99a2f0da0109e81e0c101a2b4cd8412f73f5f299e7b5b2deaf64cd2a100ac118", size = 1061694 }, { url = "https://files.pythonhosted.org/packages/54/c9/e0ead09661f58fb9ef65826ff6af7fa4386f9e52dc25ddd36cdd019235e2/shapely-2.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:183174ad0b21a81ee661f05e7c47aa92ebfae01814cd3cbe54adea7a4213f5f4", size = 2891260 },
{ url = "https://files.pythonhosted.org/packages/01/74/eaa56c4b230e874458c8d25fddf18d23e2e2625f307db227f38c37b24139/Shapely-1.8.5.post1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6fe855e7d45685926b6ba00aaeb5eba5862611f7465775dacd527e081a8ced6d", size = 2214844 }, { url = "https://files.pythonhosted.org/packages/16/6f/bcb800b2579b995bb61f429445b7328ae2336155964ca5f6c367ebd3fd17/shapely-2.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f239c1484af66bc14b81a76f2a8e0fada29d59010423253ff857d0ccefdaa93f", size = 3011154 },
{ url = "https://files.pythonhosted.org/packages/96/3a/c34e35e3181e593c72357353e8fa60052c751eff37c4a6f4e473cbf9aafd/Shapely-1.8.5.post1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec14ceca36f67cb48b34d02d7f65a9acae15cd72b48e303531893ba4a960f3ea", size = 2042386 }, { url = "https://files.pythonhosted.org/packages/c5/a0/8eeaf01fff142f092b64b53c425bd11a2c2a1564a30df283d9e8eb719fcf/shapely-2.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6220a466d1475141dad0cd8065d2549a5c2ed3fa4e2e02fb8ea65d494cfd5b07", size = 3834153 },
{ url = "https://files.pythonhosted.org/packages/11/78/a67ff51c8167323b91b1b5a687ea5e1b071a9228543eb10a243ccb0e0f2b/Shapely-1.8.5.post1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a2b2a65fa7f97115c1cd989fe9d6f39281ca2a8a014f1d4904c1a6e34d7f25", size = 1250547 }, { url = "https://files.pythonhosted.org/packages/7c/45/4a0b7e55731a410f44c4f8fbc61f484e04ec78eb6490d05576ff98efec59/shapely-2.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4822d3ed3efb06145c34d29d5b56792f72b7d713300f603bfd5d825892c6f79f", size = 4017460 },
{ url = "https://files.pythonhosted.org/packages/aa/4b/76dae50fcc9433fe512ef51e17f0944c0b2c4f4ff329916f995ae1f95a42/Shapely-1.8.5.post1-cp310-cp310-win32.whl", hash = "sha256:21776184516a16bf82a0c3d6d6a312b3cd15a4cabafc61ee01cf2714a82e8396", size = 1172164 }, { url = "https://files.pythonhosted.org/packages/bf/75/c3f3e6f5d40b9bf9390aa47d7ec56b8d56e61a30487d76d7aa06f87b3308/shapely-2.1.0-cp310-cp310-win32.whl", hash = "sha256:ea51ddf3d3c60866dca746081b56c75f34ff1b01acbd4d44269071a673c735b9", size = 1527812 },
{ url = "https://files.pythonhosted.org/packages/88/43/3a8006855fe0ae3deac065843c2f601c542f841b3c92794619d1ab291b4f/Shapely-1.8.5.post1-cp310-cp310-win_amd64.whl", hash = "sha256:a354199219c8d836f280b88f2c5102c81bb044ccea45bd361dc38a79f3873714", size = 1300823 }, { url = "https://files.pythonhosted.org/packages/71/0a/2002b39da6935f361da9c6437e45e01f0ebac81f66c08c01da974227036c/shapely-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:a6f5e02e2cded9f4ec5709900a296c7f2cce5f8e9e9d80ba7d89ae2f4ed89d7b", size = 1707475 },
] ]
[[package]] [[package]]
@ -2304,15 +2235,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/44/71/f3e7c9b2ab67e28c572ab4e9d5fa3499e0d252650f96d8a3a03e26677f53/tensorboardX-2.6.2.2-py2.py3-none-any.whl", hash = "sha256:160025acbf759ede23fd3526ae9d9bfbfd8b68eb16c38a010ebe326dc6395db8", size = 101700 }, { url = "https://files.pythonhosted.org/packages/44/71/f3e7c9b2ab67e28c572ab4e9d5fa3499e0d252650f96d8a3a03e26677f53/tensorboardX-2.6.2.2-py2.py3-none-any.whl", hash = "sha256:160025acbf759ede23fd3526ae9d9bfbfd8b68eb16c38a010ebe326dc6395db8", size = 101700 },
] ]
[[package]]
name = "termcolor"
version = "2.5.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/37/72/88311445fd44c455c7d553e61f95412cf89054308a1aa2434ab835075fc5/termcolor-2.5.0.tar.gz", hash = "sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f", size = 13057 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/be/df630c387a0a054815d60be6a97eb4e8f17385d5d6fe660e1c02750062b4/termcolor-2.5.0-py3-none-any.whl", hash = "sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8", size = 7755 },
]
[[package]] [[package]]
name = "terminado" name = "terminado"
version = "0.18.1" version = "0.18.1"
@ -2510,7 +2432,6 @@ dependencies = [
{ name = "ncls" }, { name = "ncls" },
{ name = "notebook" }, { name = "notebook" },
{ name = "numpy" }, { name = "numpy" },
{ name = "nuscenes-devkit" },
{ name = "opencv-python" }, { name = "opencv-python" },
{ name = "orjson" }, { name = "orjson" },
{ name = "pandas" }, { name = "pandas" },
@ -2534,7 +2455,6 @@ requires-dist = [
{ name = "ncls", specifier = ">=0.0.68,<0.0.69" }, { name = "ncls", specifier = ">=0.0.68,<0.0.69" },
{ name = "notebook", specifier = ">=7.0.4,<8.0.0" }, { name = "notebook", specifier = ">=7.0.4,<8.0.0" },
{ name = "numpy", specifier = ">=1.24.3,<2.0.0" }, { name = "numpy", specifier = ">=1.24.3,<2.0.0" },
{ name = "nuscenes-devkit", specifier = ">=1.1.11,<2.0.0" },
{ name = "opencv-python", specifier = ">=4.7.0.72,<5.0.0.0" }, { name = "opencv-python", specifier = ">=4.7.0.72,<5.0.0.0" },
{ name = "orjson", specifier = ">=3.9.7,<4.0.0" }, { name = "orjson", specifier = ">=3.9.7,<4.0.0" },
{ name = "pandas", specifier = ">=2.1.1,<3.0.0" }, { name = "pandas", specifier = ">=2.1.1,<3.0.0" },
@ -2549,6 +2469,7 @@ requires-dist = [
{ name = "torch", marker = "python_full_version >= '3.10' and python_full_version < '4' and sys_platform == 'linux'", url = "https://download.pytorch.org/whl/cu113/torch-1.12.1%2Bcu113-cp310-cp310-linux_x86_64.whl" }, { name = "torch", marker = "python_full_version >= '3.10' and python_full_version < '4' and sys_platform == 'linux'", url = "https://download.pytorch.org/whl/cu113/torch-1.12.1%2Bcu113-cp310-cp310-linux_x86_64.whl" },
{ name = "tqdm", specifier = ">=4.65.0,<5.0.0" }, { name = "tqdm", specifier = ">=4.65.0,<5.0.0" },
] ]
provides-extras = ["nuscenes"]
[[package]] [[package]]
name = "trap" name = "trap"
@ -2604,7 +2525,7 @@ requires-dist = [
{ name = "pyusb", specifier = ">=1.3.1,<2" }, { name = "pyusb", specifier = ">=1.3.1,<2" },
{ name = "qrcode", specifier = "~=8.0" }, { name = "qrcode", specifier = "~=8.0" },
{ name = "setproctitle", specifier = ">=1.3.3,<2" }, { name = "setproctitle", specifier = ">=1.3.3,<2" },
{ name = "shapely", specifier = ">=1,<2" }, { name = "shapely", specifier = ">=2.1" },
{ name = "simplification", specifier = ">=0.7.12" }, { name = "simplification", specifier = ">=0.7.12" },
{ name = "tensorboardx", specifier = ">=2.6.2.2,<3" }, { name = "tensorboardx", specifier = ">=2.6.2.2,<3" },
{ name = "torch", marker = "python_full_version < '3.10' or python_full_version >= '4' or sys_platform != 'linux'", specifier = "==1.12.1" }, { name = "torch", marker = "python_full_version < '3.10' or python_full_version >= '4' or sys_platform != 'linux'", specifier = "==1.12.1" },