added ruff code reivew

This commit is contained in:
ykcheungab
2026-09-27 19:21:55 +08:00
parent 07da372204
commit e2ac36269c
110 changed files with 890 additions and 426 deletions
+7 -3
View File
@@ -9,12 +9,16 @@ ORY-BOX:单传感器基础流程
"""
import os
os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0"
import cv2
import orisys
import numpy as np
import argparse
import cv2
import numpy as np
import orisys
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--video","-v", type=str, default="0", help="视频源:摄像头编号或视频文件路径")
+1
View File
@@ -18,6 +18,7 @@ import sys
os.environ.setdefault("OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS", "0")
import cv2
import orisys
from orisys.finger import FingerRuntime
+10 -9
View File
@@ -9,9 +9,10 @@ Acquisition adapters (no widgets) live in ``gui.sensors``.
Shared bootstrap: ``gui.app``, ``gui.app_paths``, ``gui.log_config``, ``gui.widgets``.
"""
from viz.contact_arrow import ContactArrowStyle
from .log_config import LOG_CONFIG, LogConfig
from .viewer3d import (
FingerDashboardWindow,
LAYOUT,
LOG_PANEL,
MESH_CONTACT_ARROW,
@@ -19,33 +20,33 @@ from .viewer3d import (
PANEL_SETUP,
TOP_ROW,
DashboardLayout,
FingerDashboardWindow,
MeshLighting,
PanelRow,
PanelSetup,
PanelSlot,
run_dashboard,
top_row_splitter_sizes,
top_row_slot_index,
top_row_splitter_sizes,
)
from viz.contact_arrow import ContactArrowStyle
__all__ = [
"DashboardLayout",
"FingerDashboardWindow",
"LAYOUT",
"LOG_CONFIG",
"LOG_PANEL",
"LogConfig",
"MESH_CONTACT_ARROW",
"MESH_LIGHTING",
"ContactArrowStyle",
"MeshLighting",
"PANEL_SETUP",
"TOP_ROW",
"ContactArrowStyle",
"DashboardLayout",
"FingerDashboardWindow",
"LogConfig",
"MeshLighting",
"PanelRow",
"PanelSetup",
"PanelSlot",
"run_dashboard",
"top_row_splitter_sizes",
"top_row_slot_index",
"top_row_splitter_sizes",
]
+1 -1
View File
@@ -34,8 +34,8 @@ def default_config_path() -> str:
def require_gui_extras() -> None:
try:
import open3d # noqa: F401
from PyQt5 import QtWidgets # noqa: F401
import pyqtgraph # noqa: F401
from PyQt5 import QtWidgets # noqa: F401
except ImportError as exc:
raise SystemExit('GUI example requires: pip install "orisys[gui]"') from exc
+3 -3
View File
@@ -1,23 +1,23 @@
"""Sensor acquisition adapters for Qt / multi-sensor viewers (no Qt widgets)."""
from . import roi_geometry
from .adapter import (
Dd06RoiAdapter,
FrameSnapshot,
OrisysSensorAdapter,
SensorAdapter,
_snapshot_from_sensor,
calibrate_normal_force,
create_sensor_adapter,
_snapshot_from_sensor,
)
from . import roi_geometry
__all__ = [
"Dd06RoiAdapter",
"FrameSnapshot",
"OrisysSensorAdapter",
"SensorAdapter",
"_snapshot_from_sensor",
"calibrate_normal_force",
"create_sensor_adapter",
"roi_geometry",
"_snapshot_from_sensor",
]
+14 -15
View File
@@ -5,11 +5,11 @@ from __future__ import annotations
import time
from abc import ABC, abstractmethod
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Optional
from typing import Any
import cv2
import numpy as np
import orisys
from .roi_geometry import (
@@ -21,7 +21,6 @@ from .roi_geometry import (
warp_roi_to_rectangle,
)
NORMAL_FORCE_CAL_SLOPE = 3.92685554668795e-05
NORMAL_FORCE_CAL_OFFSET = 0.0217596967278535
@@ -30,10 +29,10 @@ NORMAL_FORCE_CAL_OFFSET = 0.0217596967278535
class FrameSnapshot:
"""Normalized per-frame payload consumed by the Qt viewer."""
image: Optional[np.ndarray] = None
flow: Optional[np.ndarray] = None
depth: Optional[np.ndarray] = None
contour: Optional[np.ndarray] = None
image: np.ndarray | None = None
flow: np.ndarray | None = None
depth: np.ndarray | None = None
contour: np.ndarray | None = None
centroid: Any = None
# Raw SDK force channels used for curves (same units for FN/FX/FY).
normal_force: float = 0.0
@@ -43,10 +42,10 @@ class FrameSnapshot:
normal_force_calibrated: float = 0.0
fps: float = 0.0
timestamp: float = 0.0
raw_image: Optional[np.ndarray] = None
processed_image: Optional[np.ndarray] = None
flow_overlay: Optional[np.ndarray] = None
record_frame: Optional[np.ndarray] = None
raw_image: np.ndarray | None = None
processed_image: np.ndarray | None = None
flow_overlay: np.ndarray | None = None
record_frame: np.ndarray | None = None
def calibrate_normal_force(raw_value: float) -> float:
@@ -62,7 +61,7 @@ class SensorAdapter(ABC):
raise NotImplementedError
@abstractmethod
def read(self) -> Optional[FrameSnapshot]:
def read(self) -> FrameSnapshot | None:
raise NotImplementedError
@abstractmethod
@@ -89,7 +88,7 @@ def _snapshot_from_sensor(
*,
raw_image=None,
processed_image=None,
) -> Optional[FrameSnapshot]:
) -> FrameSnapshot | None:
"""Build a FrameSnapshot with HHD/forces refreshed every frame."""
if sensor is None or sensor.img is None:
return None
@@ -186,7 +185,7 @@ class OrisysSensorAdapter(SensorAdapter):
verbose=self.verbose,
)
def read(self) -> Optional[FrameSnapshot]:
def read(self) -> FrameSnapshot | None:
if self.sensor is None:
return None
img = self.sensor.get_img()
@@ -255,7 +254,7 @@ class Dd06RoiAdapter(SensorAdapter):
f"video={self._source}"
)
def read(self) -> Optional[FrameSnapshot]:
def read(self) -> FrameSnapshot | None:
if self.sensor is None or self.cap is None:
return None
+17 -16
View File
@@ -8,13 +8,14 @@ Does not import camera, ROI, or `orisys.Sensor`.
from __future__ import annotations
from dataclasses import dataclass
from typing import Literal, Optional, Sequence, Tuple
from typing import Literal
import cv2
import numpy as np
import orisys
from scipy.signal import butter, filtfilt
import orisys
FORCE_SAMPLE_RATE_HZ = 30.0
PLOT_BUFFER_POINTS = 120
PLOT_WINDOW_SEC = PLOT_BUFFER_POINTS / FORCE_SAMPLE_RATE_HZ
@@ -40,14 +41,14 @@ class ViewerFrame:
image_height: int
image_width: int
aspect_ratio: float # width / height
depth: Optional[np.ndarray]
depth: np.ndarray | None
normal_force: float
shear_x: float
shear_y: float
normal_force_calibrated: float
fps: float
timestamp: float
record_frame: Optional[np.ndarray]
record_frame: np.ndarray | None
@dataclass
@@ -57,8 +58,8 @@ class ForcePlotState:
times: np.ndarray # shape (n,)
values: np.ndarray # shape (n, 3) FN, FX, FY
sample_count: int
x_range: Tuple[float, float]
y_ranges: Tuple[Tuple[float, float], Tuple[float, float], Tuple[float, float]]
x_range: tuple[float, float]
y_ranges: tuple[tuple[float, float], tuple[float, float], tuple[float, float]]
def lowpass_filter(
@@ -87,7 +88,7 @@ def lowpass_filter(
return filtfilt(b, a, y)
def ensure_bgr(img: Optional[np.ndarray]) -> Optional[np.ndarray]:
def ensure_bgr(img: np.ndarray | None) -> np.ndarray | None:
if img is None:
return None
if img.ndim == 2:
@@ -97,14 +98,14 @@ def ensure_bgr(img: Optional[np.ndarray]) -> Optional[np.ndarray]:
return img
def image_shape_meta(img: np.ndarray) -> Tuple[int, int, float]:
def image_shape_meta(img: np.ndarray) -> tuple[int, int, float]:
"""Return (height, width, width/height) from a display image."""
h, w = int(img.shape[0]), int(img.shape[1])
aspect = float(w) / float(h) if h > 0 else 1.0
return h, w, aspect
def _base_bgr(snapshot) -> Optional[np.ndarray]:
def _base_bgr(snapshot) -> np.ndarray | None:
for attr in ("image", "processed_image", "raw_image"):
out = ensure_bgr(getattr(snapshot, attr, None))
if out is not None:
@@ -152,7 +153,7 @@ def build_display_image(
return select_display_image(snapshot)
def bgr_to_rgb_bytes(img_bgr: np.ndarray) -> Tuple[np.ndarray, int, int]:
def bgr_to_rgb_bytes(img_bgr: np.ndarray) -> tuple[np.ndarray, int, int]:
"""Convert BGR uint8 image to contiguous RGB for QImage."""
rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
if not rgb.flags["C_CONTIGUOUS"]:
@@ -231,7 +232,7 @@ class ForceHistory:
self.data[-1, 0, :] = t
self.data[-1, 1, :] = values
def _smooth_y_range(self, channel: int, ymin: float, ymax: float) -> Tuple[float, float]:
def _smooth_y_range(self, channel: int, ymin: float, ymax: float) -> tuple[float, float]:
if self._y_range_smooth[channel] is None:
smoothed = (ymin, ymax)
else:
@@ -251,7 +252,7 @@ class ForceHistory:
pad = max((smoothed[1] - smoothed[0]) * 0.12, 0.01)
return smoothed[0] - pad, smoothed[1] + pad
def plot_state(self) -> Optional[ForcePlotState]:
def plot_state(self) -> ForcePlotState | None:
n = self.sample_count
if n == 0:
return None
@@ -305,8 +306,8 @@ class QtViewerBackend:
lowpass_cutoff_hz=lowpass_cutoff_hz,
y_axis_min_span=y_axis_min_span,
)
self._start_time: Optional[float] = None
self.last_viewer_frame: Optional[ViewerFrame] = None
self._start_time: float | None = None
self.last_viewer_frame: ViewerFrame | None = None
self.arrow_background: ArrowBackground = arrow_background
def set_arrow_background(self, background: ArrowBackground) -> None:
@@ -357,7 +358,7 @@ class QtViewerBackend:
self._start_time = None
self.last_viewer_frame = None
def ingest(self, snapshot, *, now: Optional[float] = None) -> ViewerFrame:
def ingest(self, snapshot, *, now: float | None = None) -> ViewerFrame:
"""Convert a FrameSnapshot into ViewerFrame and update force history."""
display = build_display_image(snapshot, self.arrow_background)
h, w, aspect = image_shape_meta(display)
@@ -396,5 +397,5 @@ class QtViewerBackend:
self.last_viewer_frame = frame
return frame
def plot_state(self) -> Optional[ForcePlotState]:
def plot_state(self) -> ForcePlotState | None:
return self.force_history.plot_state()
+6 -6
View File
@@ -2,8 +2,8 @@
from .dashboard import FingerDashboardWindow, run_dashboard
from .layout import (
LOG_PANEL,
LAYOUT,
LOG_PANEL,
MESH_CONTACT_ARROW,
MESH_LIGHTING,
PANEL_SETUP,
@@ -13,24 +13,24 @@ from .layout import (
PanelRow,
PanelSetup,
PanelSlot,
top_row_splitter_sizes,
top_row_slot_index,
top_row_splitter_sizes,
)
__all__ = [
"DashboardLayout",
"FingerDashboardWindow",
"LAYOUT",
"LOG_PANEL",
"MESH_CONTACT_ARROW",
"MESH_LIGHTING",
"MeshLighting",
"PANEL_SETUP",
"TOP_ROW",
"DashboardLayout",
"FingerDashboardWindow",
"MeshLighting",
"PanelRow",
"PanelSetup",
"PanelSlot",
"run_dashboard",
"top_row_splitter_sizes",
"top_row_slot_index",
"top_row_splitter_sizes",
]
+25 -4
View File
@@ -3,6 +3,7 @@
from __future__ import annotations
import contextlib
import logging
import os
import sys
from dataclasses import dataclass
@@ -11,6 +12,8 @@ import cv2
DEFAULT_MAX_CAMERA_INDEX = 10
logger = logging.getLogger(__name__)
@dataclass(frozen=True)
class CameraInfo:
@@ -62,8 +65,14 @@ def _suppress_opencv_noise():
if set_level is not None and prev_level is not None:
try:
set_level(prev_level)
except Exception:
pass
except Exception as exc:
# Best-effort: a failure only leaves OpenCV probe noise suppressed,
# but report it so a stuck log level is diagnosable.
logger.warning(
"camera discovery: could not restore OpenCV log level %r: %s",
prev_level,
exc,
)
def _backend_candidates() -> list[tuple[str, int]]:
@@ -115,9 +124,21 @@ def list_cameras(max_index: int = DEFAULT_MAX_CAMERA_INDEX) -> list[CameraInfo]:
backends = _backend_candidates()
with _suppress_opencv_noise():
for index in range(0, max_index + 1):
for index in range(max_index + 1):
for backend_name, backend_api in backends:
info = _try_open(index, backend_name, backend_api)
try:
info = _try_open(index, backend_name, backend_api)
except Exception as exc:
# Same hazard as the SDK enumerator: an escaping error for one
# backend would abort the whole probe and hide every other
# camera. Skip that candidate and keep going.
logger.warning(
"camera discovery: probing index %d via %s failed: %s",
index,
backend_name,
exc,
)
continue
if info is None:
continue
if index in seen_indices:
+7 -10
View File
@@ -6,6 +6,9 @@ import math
import sys
import time
from pipeline.config import PipelineConfig
from pipeline.csv_recorder import CsvRecorder
from pipeline.service import FingerPipeline
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import (
@@ -17,23 +20,17 @@ from PyQt5.QtWidgets import (
QWidget,
)
from pipeline.config import PipelineConfig
from pipeline.csv_recorder import CsvRecorder
from pipeline.service import FingerPipeline
from gui.app_paths import resource_path
from gui.widgets import TeeStream, WidgetLogHandler, make_log_widget
from .camera_discovery import list_cameras, pick_default_camera
from .preferences import get_preferred_video_source, load_preferences, save_preferences
from .layout import (
DashboardLayout,
LAYOUT,
PANEL_SETUP,
PanelSetup,
top_row_splitter_sizes,
DashboardLayout,
)
from .mesh_view_state import MeshViewState
from .preferences import get_preferred_video_source, load_preferences, save_preferences
from .styles import STYLE
from gui.widgets import TeeStream, WidgetLogHandler, make_log_widget
from .widgets import (
ArrowPanelWidget,
ForceChartWidget,
+3 -2
View File
@@ -47,11 +47,12 @@ import math
from dataclasses import dataclass
from typing import Literal
from gui.log_config import LOG_CONFIG, LogConfig
from viz.contact_arrow import ContactArrowStyle, DEFAULT_CONTACT_ARROW_STYLE
from viz.contact_arrow import ContactArrowStyle
from viz.flow_arrow import FlowArrowStyle
from viz.render_2d import ArrowBackground, ArrowCanvasColors
from gui.log_config import LOG_CONFIG, LogConfig
PanelId = Literal["mesh", "arrows", "charts", "log", "settings"]
+1 -1
View File
@@ -4,7 +4,7 @@ from __future__ import annotations
from PyQt5.QtCore import QObject, pyqtSignal
from .layout import DashboardLayout, LAYOUT
from .layout import LAYOUT, DashboardLayout
class MeshViewState(QObject):
+3 -3
View File
@@ -3,14 +3,14 @@
from __future__ import annotations
import cv2
from pipeline.frame import FingerFrameView
from viz.render_2d import ArrowBackground, ArrowCanvasColors, render_uv_arrows
from ..layout import DashboardLayout, LAYOUT
from .image_panel import ImagePanel
from gui.widgets.qt_pixmap import ndarray_to_pixmap
from ..layout import LAYOUT, DashboardLayout
from .image_panel import ImagePanel
class ArrowPanelWidget(ImagePanel):
"""UV unrolled flow-arrow panel."""
@@ -3,14 +3,14 @@
from __future__ import annotations
import numpy as np
from pipeline.frame import FingerFrameView
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QSizePolicy
from ..layout import DashboardLayout, LAYOUT
from ..styles import LOG_FONT_PRIMARY, UI_FONT_PRIMARY
from pipeline.frame import FingerFrameView
from viz.signal_filters import lowpass_filter
from ..layout import LAYOUT, DashboardLayout
from ..styles import LOG_FONT_PRIMARY, UI_FONT_PRIMARY
def _require_pyqtgraph():
try:
@@ -2,16 +2,16 @@
from __future__ import annotations
from pipeline.frame import FingerFrameView
from PyQt5.QtCore import QEvent, Qt
from PyQt5.QtGui import QMouseEvent
from pipeline.frame import FingerFrameView
from viz.offscreen_mesh import OffscreenFingerMeshRenderer
from ..layout import DashboardLayout, LAYOUT
from ..mesh_view_state import MeshViewState
from ..mesh_render_worker import MeshRenderWorker
from gui.widgets.qt_pixmap import ndarray_to_pixmap
from ..layout import LAYOUT, DashboardLayout
from ..mesh_render_worker import MeshRenderWorker
from ..mesh_view_state import MeshViewState
from .image_panel import ImagePanel
_VIEW_ROTATE_SENSITIVITY = 0.35
@@ -2,7 +2,7 @@
from __future__ import annotations
from PyQt5.QtCore import QSize, Qt, pyqtSignal
from PyQt5.QtCore import QSize, pyqtSignal
from PyQt5.QtWidgets import (
QCheckBox,
QComboBox,
@@ -14,11 +14,11 @@ from PyQt5.QtWidgets import (
QVBoxLayout,
QWidget,
)
from orisys.finger import DEFAULT_FINGER_EXPORT_DIR
from viz.render_2d import ArrowBackground
from ..layout import DashboardLayout, LAYOUT
from orisys.finger import DEFAULT_FINGER_EXPORT_DIR
from ..layout import LAYOUT, DashboardLayout
from ..mesh_view_state import MeshViewState
from ..transport_icons import reset_icon, transport_icon
+13 -7
View File
@@ -9,12 +9,16 @@ ORY-MINI:单传感器基础流程
"""
import os
os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0"
import cv2
import orisys
import numpy as np
import argparse
import cv2
import numpy as np
import orisys
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--video","-v", type=str, default="0", help="视频源:摄像头编号或视频文件路径")
@@ -29,11 +33,13 @@ def main():
# 输入既可以是摄像头编号,也可以是视频文件路径
try:
input = int(args.video)
is_camera = True
sensor = orisys.Sensor(input, config_name=args.config, verbose=args.verbose)
except:
is_camera = False
except ValueError:
# Not a camera index: treat the argument as a video-file path. Falling back
# only on the conversion (not on Sensor construction) keeps a real
# constructor failure visible instead of retrying it as a file path.
sensor = orisys.Sensor(args.video, config_name=args.config, verbose=args.verbose)
else:
sensor = orisys.Sensor(input, config_name=args.config, verbose=args.verbose)
print("\n按键说明:'q' 退出程序,'r' 重置追踪器。")
+4 -1
View File
@@ -245,7 +245,10 @@ def main():
try:
with open(path) as fh:
rows.append(json.load(fh))
except Exception:
except Exception: # noqa: S110 - a stream that wrote no result is reported below
# A stream that crashed or produced no JSON output is expected here;
# the empty-``rows`` check below reports that case explicitly, so this
# is not a hidden failure.
pass
if not rows:
print("no stream produced results", file=sys.stderr)
+3 -2
View File
@@ -4,9 +4,10 @@ from __future__ import annotations
from dataclasses import dataclass
from orisys.finger import DEFAULT_FINGER_EXPORT_DIR
from viz.mesh_camera import DEFAULT_FINGER_VIZ_POSE
from orisys.finger import DEFAULT_FINGER_EXPORT_DIR
def mesh_threshold(mesh_map: str, threshold: float | None) -> float:
if threshold is not None:
@@ -33,7 +34,7 @@ class PipelineConfig:
profile_every: int = 30
@classmethod
def from_args(cls, args) -> "PipelineConfig":
def from_args(cls, args) -> PipelineConfig:
return cls(
video=args.video,
config=args.config,
-1
View File
@@ -7,7 +7,6 @@ from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
CSV_COLUMNS = (
"frame_index",
"timestamp_s",
+2 -2
View File
@@ -6,10 +6,10 @@ import time
from dataclasses import dataclass
import numpy as np
from orisys.finger import FingerRuntime, compute_uv_surface_frames
from viz import FrameRecorder, build_uv_surface_mesh, resolve_viz_pose_path
from orisys.finger import FingerRuntime, compute_uv_surface_frames
from .config import PipelineConfig
from .csv_recorder import CsvMeasurement
from .frame import FingerFrameView
+2 -2
View File
@@ -16,10 +16,10 @@ os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0"
import cv2
import numpy as np
import orisys
from viz import ForceChartWindow, FrameRecorder
import orisys
def open_sensor(video: str, config: str, cal: str, verbose: bool):
try:
+23 -11
View File
@@ -20,14 +20,17 @@
"""
import os
os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0"
import cv2
import orisys
import numpy as np
import multiprocessing as mp
from multiprocessing import Queue, Process
import time
import argparse
import multiprocessing as mp
import queue
import time
from multiprocessing import Process, Queue
import cv2
import orisys
def sensor_worker(sensor_id, vid_src, config_name, result_queue, stop_event, target_fps=None):
@@ -55,6 +58,7 @@ def sensor_worker(sensor_id, vid_src, config_name, result_queue, stop_event, tar
print(f"传感器 {sensor_id} 已启动" + (f"(目标帧率:{target_fps} FPS)" if target_fps else ""))
frame_interval = 1.0 / target_fps if target_fps and target_fps > 0 else 0.0
dropped_frames = 0
while not stop_event.is_set():
t_start = time.perf_counter()
@@ -95,9 +99,10 @@ def sensor_worker(sensor_id, vid_src, config_name, result_queue, stop_event, tar
# 步骤 6:将结果发送到主进程(非阻塞)
try:
result_queue.put_nowait(data)
except Exception:
# 如果队列已满,则丢弃当前帧,避免阻塞工作进程
pass
except queue.Full:
# 队列已满:丢弃当前帧,避免阻塞工作进程。这是有意的背压策略,
# 但丢帧必须可观测,否则主进程看到的低帧率无从解释。
dropped_frames += 1
except Exception as e:
print(f"传感器 {sensor_id} 处理失败:{e}")
@@ -112,7 +117,13 @@ def sensor_worker(sensor_id, vid_src, config_name, result_queue, stop_event, tar
# 释放资源
sensor.disconnect()
print(f"传感器 {sensor_id} 已停止。")
if dropped_frames:
print(
f"传感器 {sensor_id} 已停止(因结果队列已满丢弃 {dropped_frames} 帧,"
"主进程处理慢于采集)。"
)
else:
print(f"传感器 {sensor_id} 已停止。")
except Exception as e:
print(f"传感器 {sensor_id} 初始化失败:{e}")
@@ -193,7 +204,8 @@ def main():
while True:
try:
data = queue.get_nowait()
except:
except queue.Empty:
# 队列已排空:正常结束内层循环,不是错误。
break
if data is not None:
+9 -9
View File
@@ -1,5 +1,7 @@
"""Shared visualization helpers for Orisys example scripts."""
from .finger_mesh_viewer import FingerMeshViewer
from .flow_arrow import DEFAULT_FLOW_ARROW_STYLE, FlowArrowOverlay, FlowArrowStyle
from .force_charts import ForceChartWindow
from .mesh_camera import (
DEFAULT_FINGER_VIZ_POSE,
@@ -8,33 +10,32 @@ from .mesh_camera import (
camera_look_at_from_world_to_cam,
resolve_viz_pose_path,
)
from .mesh_viewer import UVMeshViewer, build_uv_surface_mesh
from .offscreen_mesh import OffscreenFingerMeshRenderer
from .recording import FrameRecorder
from .render_2d import (
DEFAULT_ARROW_CANVAS_COLORS,
ArrowBackground,
ArrowCanvasColors,
DEFAULT_ARROW_CANVAS_COLORS,
depth_colormap,
frame_to_bgr,
render_contact_panel,
render_depth_panel,
render_uv_arrows,
)
from .flow_arrow import DEFAULT_FLOW_ARROW_STYLE, FlowArrowOverlay, FlowArrowStyle
from .finger_mesh_viewer import FingerMeshViewer
from .mesh_viewer import UVMeshViewer, build_uv_surface_mesh
from .recording import FrameRecorder
from .signal_filters import lowpass_filter
__all__ = [
"ArrowBackground",
"ArrowCanvasColors",
"DEFAULT_ARROW_CANVAS_COLORS",
"DEFAULT_FLOW_ARROW_STYLE",
"ArrowBackground",
"ArrowCanvasColors",
"FingerMeshViewer",
"FlowArrowOverlay",
"FlowArrowStyle",
"FingerMeshViewer",
"ForceChartWindow",
"FrameRecorder",
"OffscreenFingerMeshRenderer",
"UVMeshViewer",
"apply_mesh_lighting",
"apply_view_from_world_to_cam",
@@ -43,7 +44,6 @@ __all__ = [
"depth_colormap",
"frame_to_bgr",
"lowpass_filter",
"OffscreenFingerMeshRenderer",
"render_contact_panel",
"render_depth_panel",
"render_uv_arrows",
+5 -1
View File
@@ -8,7 +8,11 @@ import numpy as np
from orisys.finger.viewer import UVMeshViewer
from .contact_arrow import ContactArrowOverlay, ContactArrowStyle, DEFAULT_CONTACT_ARROW_STYLE
from .contact_arrow import (
DEFAULT_CONTACT_ARROW_STYLE,
ContactArrowOverlay,
ContactArrowStyle,
)
from .flow_arrow import DEFAULT_FLOW_ARROW_STYLE, FlowArrowOverlay, FlowArrowStyle
+2 -1
View File
@@ -2,8 +2,9 @@
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Callable, Literal
from typing import Literal
import cv2
import numpy as np
+5 -1
View File
@@ -1,4 +1,8 @@
"""Re-exports for finger 3D mesh examples; core viewer lives in orisys.finger."""
from orisys.finger.mesh import * # noqa: F403
from orisys.finger.viewer import UVMeshViewer, init_uv_mesh_viewer, update_uv_mesh_viewer # noqa: F401
from orisys.finger.viewer import ( # noqa: F401
UVMeshViewer,
init_uv_mesh_viewer,
update_uv_mesh_viewer,
)
-1
View File
@@ -2,7 +2,6 @@
from __future__ import annotations
import os
from pathlib import Path
import cv2
+1
View File
@@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Literal
import cv2
import numpy as np
import orisys
if TYPE_CHECKING:
+1
View File
@@ -5,6 +5,7 @@ from __future__ import annotations
import numpy as np
from scipy.signal import butter, filtfilt
def lowpass_filter(data, cutoff_hz=5, sample_rate_hz=30, order=2) -> np.ndarray:
"""Zero-phase Butterworth low-pass filter for uniformly sampled 1-D data."""
y = np.asarray(data, dtype=np.float64)