twanghcmut's picture
download
raw
1.94 kB
import numpy as np
def plane_pointmap(camera, intrinsics, size, table_height, mask, object_height=0.045):
camera, intrinsics = np.asarray(camera, float), np.asarray(intrinsics, float)
if camera.shape != (4, 4) or intrinsics.shape != (3, 3):
raise ValueError(
"Camera pose and intrinsics must have shapes (4, 4) and (3, 3)"
)
if (
not np.isfinite(camera).all()
or not np.isfinite(intrinsics).all()
or not np.isfinite([table_height, object_height]).all()
or object_height <= 0
):
raise ValueError(
"Camera and plane calibration must be finite with positive object height"
)
width, height = size
if mask.shape != (height, width):
raise ValueError("Mask and camera image size must match")
yy, xx = np.mgrid[:height, :width]
rays = np.stack((xx, yy, np.ones_like(xx)), axis=-1) @ np.linalg.inv(intrinsics).T
world_rays = rays @ camera[:3, :3].T
surface_height = table_height + mask.astype(float) * object_height
distance = np.divide(
surface_height - camera[2, 3],
world_rays[..., 2],
out=np.full((height, width), np.nan),
where=np.abs(world_rays[..., 2]) > 1e-8,
)
valid = np.isfinite(distance) & (distance > 0) & (distance < 4)
points = rays * distance[..., None]
points[~valid] = np.nan
return points.astype(np.float32)
def contact_table_height(
keypoints, contact_start, contact_end, object_height=0.045, finger_radius=0.0065
):
if not 0 <= contact_start < contact_end <= len(keypoints):
raise ValueError("Contact interval must lie within the video")
tips = np.asarray(keypoints)[contact_start:contact_end, [4, 8, 12, 16, 20], 2]
if not np.isfinite(tips).all():
raise ValueError("Contact fingertip positions must be finite")
return float(np.quantile(tips.min(axis=1), 0.25) - object_height - finger_radius)

Xet Storage Details

Size:
1.94 kB
·
Xet hash:
60287ed9250a3ef063393d98ab2fec8882b706b40a7d6e82234eaf0d77a9e821

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.