Skip to content

dataset_resolver: make the KITTI lidar2img product the one its docstring states - #9

Open
egeboy35 wants to merge 1 commit into
lkk688:mainfrom
egeboy35:fix/kitti-lidar2img-shape
Open

dataset_resolver: make the KITTI lidar2img product the one its docstring states#9
egeboy35 wants to merge 1 commit into
lkk688:mainfrom
egeboy35:fix/kitti-lidar2img-shape

Conversation

@egeboy35

Copy link
Copy Markdown

_kitti_lidar2img documents itself as

3x4 projection: lidar2img = P2 @ R0_rect @ Tr_velo_to_cam

and then computes

Rt = (R0 @ Tr)[:3, :]   # 3x4
return (P2 @ Rt)        # (3,4) @ (3,4)

_read_kitti_calib — in the same module — returns P2 as 3×4 and both R0_rect and Tr_velo_to_cam as 4×4. That slice therefore leaves a (3,4) @ (3,4) matmul, which has no valid shape.

Measured, with a real KITTI calib

P2 (3, 4)   R0_rect (4, 4)   Tr_velo_to_cam (4, 4)
Rt = (R0 @ Tr)[:3, :]  ->  (3, 4)
P2 @ Rt                ->  ValueError: matmul: Input operand 1 has a mismatch
                           in its core dimension 0, with gufunc signature
                           (n?,k),(k,m?)->(n?,m?) (size 3 is different from 4)

There is no input that works. The shapes come from the reader in the same module, so the function raises every time it is reached.

It is reached

iter_kitti_like builds it for every frame that has a calib file (line 181), and make_iterator routes --dataset kitti and --dataset waymokitti there. eval_infer_vis.py:530 imports make_iterator. So the KITTI path stops on its first calibrated frame.

The change

Dropping the slice restores the docstring's product — (3,4) @ (4,4) — and also keeps the translation column of R0_rect, which the 3×4 slice discarded even where the shapes happened to line up.

Tests

Adds bevdet/tests/test_kitti_lidar2img.py — 11 tests, pure numpy, no dataset download and no GPU. The calibration is KITTI object 000000 written out as arrays.

Against this branch: 11 passed. Against the file as it stands on main: 7 failed, 4 passed, every failure the same ValueError:

FAILED test_it_returns_a_projection_instead_of_raising
FAILED test_it_equals_the_product_its_docstring_states
FAILED test_a_lidar_point_lands_in_front_of_the_camera
FAILED test_a_point_behind_the_lidar_projects_behind_the_camera
FAILED test_moving_along_the_lidar_y_axis_moves_the_pixel_horizontally
FAILED test_the_rectification_translation_is_not_discarded
FAILED test_it_survives_the_reader_end_to_end

The 4 that pass either way are the premise (P2 is 3×4, the other two are 4×4) and the three incomplete-calib cases, which the reader rejects before the projection is reached — unchanged behaviour.

Beyond "it does not raise", the tests check the geometry: a point 10 m ahead projects inside the 1242×375 KITTI frame with positive depth, a point behind the lidar projects behind the camera, and moving along lidar +y moves the pixel left. Those would still pass if the product were merely well-shaped but wrong, which is why they are there rather than a shape assertion alone.

pytest DeepDataMiningLearning/bevdet/tests/test_kitti_lidar2img.py

@egeboy35
egeboy35 force-pushed the fix/kitti-lidar2img-shape branch from 134319d to b575d10 Compare September 1, 2026 12:28
…ing states

`_kitti_lidar2img` documents itself as

    3x4 projection: lidar2img = P2 @ R0_rect @ Tr_velo_to_cam

and then computes

    Rt = (R0 @ Tr)[:3, :]   # 3x4
    return (P2 @ Rt)        # (3,4) @ (3,4)

`_read_kitti_calib` returns P2 as 3x4 and both R0_rect and Tr_velo_to_cam as
4x4, so that slice leaves a (3,4) @ (3,4) matmul, which has no valid shape.
Called with a real KITTI calib:

    P2 (3, 4)   R0_rect (4, 4)   Tr_velo_to_cam (4, 4)
    Rt = (R0 @ Tr)[:3, :]  ->  (3, 4)
    P2 @ Rt                ->  ValueError: matmul: Input operand 1 has a
                               mismatch in its core dimension 0 ...
                               (size 3 is different from 4)

There is no input that works: the shapes come from the reader in the same
module, so the function raises every time it is reached.

It is reached. `iter_kitti_like` builds it for every frame that has a calib
file (line 181), and `make_iterator` routes `--dataset kitti` and
`--dataset waymokitti` there. `eval_infer_vis.py:530` imports `make_iterator`.
So the KITTI path stops on its first calibrated frame.

Dropping the slice restores the docstring's product -- (3,4) @ (4,4) -- and
also keeps the translation column of R0_rect, which the 3x4 slice discarded
even where the shapes happened to line up.

Adds bevdet/tests/test_kitti_lidar2img.py -- 11 tests, pure numpy, no dataset
download and no GPU. The calibration is KITTI object 000000 written out as
arrays. Against this branch: 11 passed. Against the file as it stands on main:
7 failed, 4 passed, every failure the same ValueError:

    FAILED test_it_returns_a_projection_instead_of_raising
    FAILED test_it_equals_the_product_its_docstring_states
    FAILED test_a_lidar_point_lands_in_front_of_the_camera
    FAILED test_a_point_behind_the_lidar_projects_behind_the_camera
    FAILED test_moving_along_the_lidar_y_axis_moves_the_pixel_horizontally
    FAILED test_the_rectification_translation_is_not_discarded
    FAILED test_it_survives_the_reader_end_to_end

The 4 that pass either way are the premise (P2 is 3x4, the other two are 4x4)
and the three incomplete-calib cases, which the reader rejects before the
projection is reached -- unchanged behaviour.

Beyond "it does not raise", the tests check the geometry: a point 10 m ahead
projects inside the 1242x375 KITTI frame with positive depth, a point behind
the lidar projects behind the camera, and moving along lidar +y moves the pixel
left. Those would still pass if the product were merely well-shaped but wrong,
which is why they are there rather than a shape assertion alone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@egeboy35
egeboy35 force-pushed the fix/kitti-lidar2img-shape branch from b575d10 to 5ae31fe Compare September 1, 2026 12:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant