System designHow-to

Image to map homography: map tracking points onto a ground plane

Four surveyed floor points give a ground-plane homography that maps image pixels to map coordinates in metres, with the solve and error budget worked through.

LumaSpec Vision11 min read Share on LinkedIn

On this page 9 sections
  1. 01When a ground-plane homography is the right tool
  2. 02What you need
  3. 03Calibrate and map, step by step
  4. 04Worked example: one camera over a load-in bay
  5. 05Track the contact point, not the box centre
  6. 06Verify the calibration before go-live
  7. 07When the usual answer is wrong
    1. The floor refuses to stay flat
    2. Wide lenses bend straight lines
    3. The destination is a Mercator map
    4. The depth-camera route
  8. 08Where this leaves you
  9. 09Questions

You have a fixed camera watching people, AGVs or totes cross a floor, and you want their positions on a plan or map view in metres, not pixels. You do not need a depth camera to get there. If the targets stay on one flat plane and the camera never moves, four surveyed points are enough: they define a ground-plane homography that converts every tracked pixel into map coordinates directly, with no lens model and no depth map. This guide walks through the calibration, the solve, a fully worked example with the arithmetic on show, the error budget, and the point at which a 3D sensor becomes the better tool.

When a ground-plane homography is the right tool

A camera that watches a flat plane sees that plane through a projective mapping called a homography: a 3x3 matrix that turns every pixel (u, v) into plan coordinates (X, Y) in metres.

X = (h11*u + h12*v + h13) / w Y = (h21*u + h22*v + h23) / w w = h31*u + h32*v + 1

The matrix carries 8 degrees of freedom: the overall scale is arbitrary, so h33 is set to 1 and 8 coefficients remain to find. Each surveyed point pair supplies 2 equations, which is why 4 pairs solve the system exactly, and why 6-10 pairs let the solver average your clicking and survey errors instead of inheriting them.

Three conditions make this the right tool: a fixed camera, everything you track touching one plane, and access to survey that plane. A camera over a load-in bay, a pallet zone or a floor intersection meets all three. It is the same mathematics as mapping points into a warped image, pointed at the world instead of a rectified picture: there the image is warped, here the point coordinates are. And if you do know the lens geometry — focal length, mounting height, tilt — you can derive the same matrix from the pose; ground-plane pose from one image using four known points works that variant.

What you need

  • A fixed camera, bolted to a wall or mast, with focus and zoom locked. The method never reads intrinsics, so any machine-vision camera qualifies; the camera finder filters by resolution and interface if you are fitting a new one.
  • Six to ten surveyable marks on the plane: floor-tape corners, bolt heads, expansion-joint crosses. A tape measure or laser distance meter good to 1 cm is plenty.
  • A viewer that reports pixel coordinates, so you can click each mark and read its (u, v).
  • A solver: OpenCV's findHomography, or roughly 20 lines of numpy around a linear least-squares solve.
  • A detector whose output you refine to a contact point — feet, tyre patches, tote bottoms.

Calibrate and map, step by step

  1. Fix the camera and its lens. Bolt the mount, set focus and iris, and log the pose. Rerun the calibration after any physical change; see the warning above.
  2. Place and survey 6-10 points on the plane. Spread them to the edges of the tracking area, not a tidy cluster in the middle. Measure X and Y in your plan frame to about 1 cm with a tape or laser distance meter.
  3. Click the matching pixels. Zoom into each mark and record its pixel position to 1-2 px. Keep a written pairing table so pixel and metre values stay matched.
  4. Build the two coordinate lists. src holds the clicked pixels, dst holds the surveyed metres, both as floating-point pairs (Point2f in the classic API).

Each pair (u, v) mapped to (X, Y) contributes two linear equations in the 8 unknowns:

u*h11 + v*h12 + h13 - X*u*h31 - X*v*h32 = X u*h21 + v*h22 + h23 - Y*u*h31 - Y*v*h32 = Y
  1. Solve for H. Four pairs give 8 equations for 8 unknowns; extra pairs are averaged as least squares. In code, with the values from the worked example below:
import numpy as np
import cv2

# Illustrative values from the worked example below.
src = np.array([[300., 900.], [1700., 900.], [1700., 1900.], [300., 1900.]])      # clicked pixels
dst = np.array([[0.000, 0.546], [6.135, 0.526], [5.641, 3.707], [0.000, 3.837]]) # surveyed metres

H, _ = cv2.findHomography(src, dst)   # 3x3 matrix
H = H / H[2, 2]                       # normalise so h33 = 1

u, v = 960.0, 1400.0                  # a tracked feet point, pixels
q = H @ np.array([u, v, 1.0])         # homogeneous plan coordinates
X, Y = q[0] / q[2], q[1] / q[2]       # divide by w -> metres
# -> X ~= 2.82 m, Y ~= 2.22 m on the plan
  1. Check a point you did not calibrate on. With exactly four pairs the solve reproduces them exactly, so a zero residual there proves nothing. Hold one marker back and map it through H; it should land within two to three times your survey accuracy.
  2. Map contact points, not box centres. Run each detection's floor contact point through H every frame — the two divisions in the code above. The next section shows what a head point costs you.
  3. Leave a permanent check in view. Paint a floor target, map it every shift, and recalibrate when its logged error passes twice the survey tolerance.

Worked example: one camera over a load-in bay

A 1,920 x 1,080 fixed camera watches a load-in bay. Four floor-tape corners sit near the frame corners, and a laser distance meter places them in the plan frame:

Marker Pixel (u, v) Plan (X, Y), m
P1 (300, 900) (0.000, 0.546)
P2 (1700, 900) (6.135, 0.526)
P3 (1700, 1900) (5.641, 3.707)
P4 (300, 1900) (0.000, 3.837)

The quad spans the frame corners, so nothing is collinear. Solving on these pairs returns, to the digits that matter:

H = | 0.005000 0 -1.5 | | 0 0.004000 -3.0 | | 0.00003 0.00010 1 |

A detector fires on a person at pixel (960, 1400); the feet point maps like this:

w = 0.00003*960 + 0.00010*1400 + 1 = 0.0288 + 0.1400 + 1 = 1.1688 X = (0.0050*960 - 1.5) / 1.1688 = 3.300 / 1.1688 = 2.823 m Y = (0.0040*1400 - 3.0) / 1.1688 = 2.600 / 1.1688 = 2.224 m

The person stands 2.82 m across and 2.22 m out from the far edge of the plan. One pixel is worth 4.03 mm at the near markers (5.641 m over 1,400 px) and 4.38 mm at the far markers (6.135 m over 1,400 px), so a 2 px click error alone is worth 8-9 mm.

Track the contact point, not the box centre

The homography is only true for points that lie on the calibrated plane. A detector box's centre rides at roughly half the object's height, and height buys parallax error through:

apparent ground range = h*R / (h - z) position error = R*z / (h - z)

Here h is the camera height above the plane, z the point's height above it, and R the point's true horizontal distance from the camera's ground point. Work the numbers for a camera 6 m up, a true range of 4 m and a head point 1.7 m above the floor: the head appears to stand at 64/(6-1.7) = 24/4.3 = 5.58 m, an error of 1.58 m. Use the centre of the same box, about 0.9 m up, and the error is still 40.9/5.1 = 0.71 m.

So the rule is mechanical: track feet, tyre contact patches or the bottom edge of the box, and feed those pixels to H. Bottom-edge tracking needs no extra model and removes the dominant error in this chain.

Verify the calibration before go-live

  1. Hold-back check. Keep a fifth surveyed marker out of the solve. In the example, a pallet corner taped at plan (3.20, 1.80) m sits at pixel (1041, 1272). Mapping it through H: w = 0.000031041 + 0.000101272 + 1 = 1.158, X = 3.705/1.158 = 3.198 m, Y = 2.088/1.158 = 1.802 m — within 2 mm of the tape on both axes. That 2 mm is the number to demand from your own build; with a real tape survey and real clicks, expect 10-30 mm instead of this noise-free figure.
  2. Far field. Metres-per-pixel grow with range (4.03 to 4.38 mm/px across the example bay), and tilt errors scale with ground distance: the 0.3 degree bump from the warning is worth 2 cm at 4 m and 5 cm at 10 m. Quote accuracy per zone, not for the frame.
  3. Vanishing-line margin. w = 0 is the horizon, where the mapping divides by zero. Across the example frame w ranges from 1.00 to 1.17 — comfortable. If your tracked region pushes w below about 0.2, errors explode; crop the region away from the horizon.
  4. Flatness. Walk the plane with the parallax formula: every millimetre the floor deviates from the plane becomes millimetres of position error at mid-range. A dip, a ramp or a dock leveller mid-travel needs its own zone calibration.

The same discipline applies to depth sensors — quantifying flat-plane error at the frame edges walks the equivalent check for a 3D camera.

When the usual answer is wrong

The floor refuses to stay flat

A drain slope at the bay door, stock piled against a wall, a leveller in motion: any of these puts real floor outside the calibrated plane. Split the scene into zones, each with its own four points, or change sensor — the depth route below. Do not fold a sloped area into one solve; the residuals will look acceptable near the calibration marks and read decimetres away from them.

Wide lenses bend straight lines

A short focal length bows straight floor lines near the frame edges. The four-point solve absorbs some of that bend around the calibration points and none of it elsewhere, and tens of pixels of residual bow cost centimetres at mid-range. If expansion joints look curved in the viewer, undistort the stream with a lens calibration before solving; every common library ships the model.

The destination is a Mercator map

The solver does not care what dst means, so a Mercator view works: feed projected easting and northing in metres (EPSG:3857 for web maps) and the same four pairs produce the same kind of matrix. Subtract a local origin from the coordinates first — easting values in the millions wreck the conditioning of the linear solve — and add it back afterwards. One conversion matters: Mercator metres are not ground metres. Multiply by the cosine of your latitude; at 51.5 degrees N the factor is 0.62, so 100 projected metres is 62 m on the ground. Across one scene of tens of metres that factor barely changes, and if you need ground distances anyway, calibrate in local metres and convert once with a fixed translation-rotation-scale fitted from two known points.

The depth-camera route

If targets leave the floor, the floor will not stay flat, or the camera cannot be locked, a depth camera ends the debate. It returns a calibrated X, Y, Z for every pixel, so a head 1.7 m above the floor maps as correctly as the feet beneath it, and the transform to plan coordinates becomes one fixed rotation and translation with no survey at all. The deprojection calculation from depth map to point cloud shows how pixel plus depth becomes 3D points, and mapping image pixels to 3D points from a bounding box covers attaching that depth to detections.

For a fixed overhead view of a working zone, a ToF sensing camera such as the MV-DT01WMU captures the depth of the whole scene in one shot:

3D sensorsHikrobot MV-DT01WMU ToF sensing cameraMV-DT01WMU
Type
Depth / ToF camera
Price on requestView and quote

For close-in indoor zones such as a pallet drop area or a robot cell approach, a projected structured-light 3D camera such as the MV-DPS200P-02 does the same job from a fixed mount:

3D sensorsHikrobot MV-DPS200P-02 Projected structured-light 3D cameraMV-DPS200P-02
Type
Stereo / structured light
$8,829.00 · quotedView and quote

Where this leaves you

Fixed camera, flat plane, contact points: solve a homography from four surveyed pairs, hold one point back to prove it, and map feet — the whole chain needs no depth camera and lands within 1-3 cm over a bay-sized scene. Points above the plane, slopes or a moving camera: change the sensor, not the maths, and let a 3D camera give you Z per pixel. Both routes end in the same place — tracked objects plotted in metres on your plan.

Compare depth options in the 3D sensors range, or read the systems guides for the surrounding coordinate-transform work. If a scene refuses both routes, send the applications team your layout with a frame attached. Fitting a new fixed camera to a zone? The configurator below starts at the camera step.

Build the whole station

The configurator matches a camera, lens, light, light controller and cables to each other, step by step, and lists only parts that fit what you already picked.

Start with the camera

Questions

How many point pairs does a ground-plane homography need?

Four is the mathematical minimum: the matrix carries 8 degrees of freedom and each pair contributes 2 equations. Practically, use 6-10 pairs spread across the tracking area so the solver averages your click and survey errors. Keep the set off any single line — points bunched along one edge or in one small patch make the solve ill-conditioned, and the far field then drifts by decimetres while the near field still looks fine.

Can the destination be a Mercator map instead of local metres?

Yes. Feed the solver projected easting and northing, such as EPSG:3857 web-map metres, and the four-pair solve runs unchanged, because a projected map is still a plane. Just subtract a local origin before solving and add it back afterwards; Mercator metres also overstate ground distance by 1/cos(latitude), about 1.6x at 51.5 degrees N.

How accurate is a ground-plane homography in practice?

Add up three parts: survey error of about 1 cm with a tape, click error of 1-2 pixels worth 8-9 mm in the worked example, and any deviation of the floor from a true plane. Residuals of 10-30 mm over a bay-sized scene are normal; millimetre results need a total-station survey, a distortion-corrected lens and contact-point tracking. State accuracy per zone, because it degrades toward the far field.

Do I need camera intrinsics or a lens calibration for this?

No. The solve runs straight on clicked pixels, with no focal length, sensor size or distortion model in sight. Add undistortion only when straight floor lines bow visibly in the viewer — a few tens of pixels of bend at the corners already costs centimetres at the far markers. Intrinsics come back into play only on the depth route, where a calibrated 3D camera deprojects pixel plus depth.

What happens if the camera gets bumped or refocused?

The matrix belongs to one camera pose, so any bump, zoom or focus change invalidates it. A 0.3 degree tilt moves mapped points about 5 cm at 10 m of ground range; a zoom change can move them metres. Keep a painted floor target in view, re-map it every shift, and rerun the four-click solve whenever its logged error passes twice the survey tolerance.

Does this work from a camera that moves, for example on a vehicle?

Not with one matrix. A moving camera changes the plane mapping every frame, so you would need live pose from wheel odometry or an external tracker feeding the chain. The dependable route is one fixed camera per zone with its own four-point calibration, handing tracked objects between zones, or an on-vehicle depth camera that carries its own per-frame pose.