Seeing with a Camera, step 3
From pixels back to the table
Turn a pixel into a ray and intersect it with the plane the balls rest on to get a 3-D position.
Builds on Frames & homogeneous transforms, from the free Foundations.
Write and run this step in the simulator with ProPixels are rays
Projection throws depth away: every point on a line through the lens lands on the same pixel. So going backwards, a pixel doesn't give you a point. It gives you a ray:
is the ray's direction in the camera frame, scaled so that . turns it into world coordinates, and the ray starts at the camera's position .
A known plane fixes the depth
One camera can't tell how far along the ray a ball is. But you know something extra: every ball rests on the table, so its centre is at height m. Walk along the ray until you reach that height:
The camera looks down, so is negative, and so is . That makes positive. Warehouse robots use this trick to find boxes on a conveyor, and cars use it to place lane markings on the road.
Another route: depth
img.depth[v, u] is the distance along the camera's axis to whatever that pixel sees. Scaling by it gives the 3-D point directly in the camera frame, even off the table, and and then carry it into the world. But it lands on the ball's surface, not its centre. Depth cameras and stereo rigs give you that image; the plane trick needs only an ordinary camera.
Your task
Implement pixel_to_world(u, v) so it returns np.array([x, y, z]) on the plane . The starter finds each ball with a step-2 find_ball and prints your estimate next to the truth.
The grader checks 20 pixels, and each answer must be within 5 mm.