System designHow-to

MATLAB dot pattern camera calibration: detect the points yourself

MATLAB has no dot pattern detector: for camera calibration you find the circle centers yourself and feed them to estimateCameraParameters.

LumaSpec Vision12 min read Share on LinkedIn

On this page 9 sections
  1. 01Does MATLAB have a ready-made dot chart calibration function?
  2. 02How do you detect the dot centers yourself?
  3. 03How large should each dot be on the sensor, and from how far?
  4. 04How do you keep the point order consistent across images?
  5. 05What is the full workflow from chart to parameters?
  6. 06How do you know the calibration is good enough?
  7. 07When is a dot chart the wrong pattern?
  8. 08What should you check before the first capture?
  9. 09Questions

You have a dot chart, a MATLAB licence and a camera to calibrate. The blunt answer first: MATLAB ships no equivalent of OpenCV's findCirclesGrid — nothing in the toolbox finds a circle grid and hands you ordered points — so dot detection is code you write yourself. That is a smaller job than it sounds. The Computer Vision System Toolbox function estimateCameraParameters calibrates from any paired set of world points and image points, whatever pattern they came from: detect the circle centers, order them consistently, and the rest of the pipeline is standard. This guide covers the two-stage detector, the chart-to-sensor geometry that makes sub-pixel centers possible, the ordering trap hiding in symmetric grids, and the numbers that tell you the result is good.

Does MATLAB have a ready-made dot chart calibration function?

No: nothing in the Computer Vision System Toolbox detects a dot chart for you, but estimateCameraParameters calibrates from any paired world and image points, so the detector is the only code you write — about 30 lines.

The bundled pattern detector and the calibration app are built around checkerboards; the circle-grid route that OpenCV exposes as findCirclesGrid has no counterpart. The gap sits entirely on the detection side. On the estimation side, estimateCameraParameters takes two arrays: world points, the dot positions on the chart in millimetres, and image points, the detected centers in pixels, one plane per capture. It never asks what pattern the points came from.

You supply the chart. Any flat dot grid works — the rail below shows a board carrying a 0.5 mm dot grid on a 76 × 76 mm area:

Lens accessoriesCalibration boards and depth-of-field rulers, dot diameter 0.5 mm, dot grid, 76 x 76 mm (LS-LXR-0029)LS-LXR-0029
Type
Calibration targets
$189.00View partBuild a system with it

Read the dot pitch from the chart drawing and confirm it once with calipers, because the pitch you measure is the pitch the calibration believes. Boards like this sit with calibration targets and other lens accessories; if the camera is still open, area scan cameras is where the mono USB3 and GigE bodies live.

How do you detect the dot centers yourself?

Two stages: imfindcircles locates each dot to within about a pixel, then a background-corrected weighted centroid over a small patch around each hit refines the center to roughly 0.05–0.1 px on dots 8–30 px across.

Stage one, imfindcircles: give it the radius range in pixels that the geometry section computes, tell it the dots are darker than the background, and keep only the confident hits. Stage two does the accuracy work. Around each rough center take a patch with a radius of dot radius plus 3 px, subtract the local background, and take the intensity-weighted mean of what is left:

% imfindcircles and estimateCameraParameters are the toolbox calls;
% every other name below is ours.
img = frames{1};                               % uint8 matrix, one frame
[xc, yc, rFound] = imfindcircles(img, [8 16]); % rough centers, pixels

patchR = round(median(rFound)) + 3;            % window radius, pixels
cx = zeros(size(xc));  cy = zeros(size(yc));
for k = 1:numel(xc)
    x0 = round(xc(k));  y0 = round(yc(k));
    p  = double(img(y0-patchR:y0+patchR, x0-patchR:x0+patchR));
    w  = max(median(p(:)) - p, 0);             % dark dot: mass above background
    [X, Y] = meshgrid(x0-patchR:x0+patchR, y0-patchR:y0+patchR);
    cx(k) = sum(w .* X, 'all') / sum(w, 'all');
    cy(k) = sum(w .* Y, 'all') / sum(w, 'all');
end

The test that proves the refinement: with the chart static, repeat over ten frames and one dot's center should repeat within about 0.1 px. Scatter near a pixel means the patch overlaps a neighbour dot or the exposure is starved.

Two failure modes eat real accuracy. A dot clipped by the image border or the board edge has lost mass on one side, and its centroid shifts toward the missing side — reject any dot whose patch is not fully inside the image. And with dark dots the weight must be mass above the local background, never raw intensity; grayscale centroid of a dark circle: invert for sub-pixel works through that inversion. Before batch-processing, overlay the accepted centers on one frame the way uniform pixel grid overlay for dot-target calibration shows and look at it.

How large should each dot be on the sensor, and from how far?

Between 8 and 30 pixels across: below that the centroid wobbles with pixel phase, above that the dot goes soft before you gain anything — the worked example below lands at about 21 px.

Start from the sensor, not the lens. A 1"-class 20 MP sensor has pixels near 2.4 µm, so its active area is about 13.1 × 8.8 mm. Frame a 76 × 76 mm chart with margin and the numbers fall out:

m = sensor height / framed chart height WD = f × (1 + m) / m dot image diameter = dot diameter × m
  • Frame the chart at 85 mm across the sensor's short axis: m = 8.8 mm / 85 mm = 0.103.
  • The long axis then covers 13.1 mm / 0.103 = 127 mm.
  • A 50 mm lens puts the working distance at WD = 50 mm × (1 + 1/0.103) ≈ 535 mm.
  • Each 0.5 mm dot images to 0.5 mm × 0.103 = 51.5 µm, which is 51.5 / 2.4 ≈ 21 px — inside the band.
  • Scale at the chart: 127 mm / 5472 px ≈ 23 µm per pixel.
How sensor width, working distance and field of view set the focal length Rays from the edges of the sensor pass through the lens and spread to the edges of the field of view. The ratio of sensor width to field of view is the magnification m.CameraField of view (FOV)Working distance (WD)≈ fsensor width slensm = s / FOVf = WD × m / (1 + m)
How sensor width, working distance and field of view set the focal length. Rays from the edges of the sensor pass through the lens and spread to the edges of the field of view. The ratio of sensor width to field of view is the magnification m.

The calculator below runs the same three lines for any sensor and chart you type in:

Lens focal length, field of view and working distance
Units
Solve for
Focal length
– mm
Field of view
– mm
Working distance
– mm
Magnification
– x
Angle of view
– °
Pixel on the part
– mm

Thin-lens model: m = sensor width / field of view, f = WD × m / (1 + m). Accurate to a few percent above about 150 mm; check the lens's minimum object distance.

Find lenses with this focal length Open the full calculator

Stop down to f/8 and leave it there. Depth of field at that stop runs about 2 × N × c × (1 + m) / m²: with the circle of confusion at 2 px (4.8 µm) that is 2 × 8 × 0.0048 mm × (1.103 / 0.0106) ≈ 8 mm, or ±4 mm around focus. Tilt poses 10–20°; at 20° the far edge of a 76 mm chart recedes 76 mm × sin 20° ≈ 26 mm, so those dots defocus — but the blur is symmetric, which the centroid tolerates, and foreshortening compresses them only to cos 20° = 0.94. Diffraction at f/8 gives an Airy diameter near 2.44 × 0.55 µm × 8 ≈ 10.7 µm, about 4.5 px, again symmetric and again harmless.

Mount the chart, and lock exposure at 5–10 ms with gain at minimum under a diffuse area light. Motion is the one input this pipeline cannot absorb, which is also why the camera below carries a warning.

On the camera side, the MV-CS200-10UM is a 20 MP mono body in USB3.0 with a 1" sensor and a C-mount:

Area scan camerasHikrobot MV-CS200-10UM 20 MP Area Scan Camera, USB3.0, IMX183, 2nd Gen., MonoMV-CS200-10UM
Sensor format
1"
Lens mount
C-mount
Interface
USB3
Resolution
16-25 MP
$759.00View partBuild a system with it

Mono also beats colour here: a Bayer sensor interpolates the very edges your centroid weighs, while mono keeps every photosite a measured value — the working habit circular grid camera calibration with monochrome images goes through. The camera finder filters mono bodies by mount and shutter, and the system configurator bundles camera, lens and chart in one pass.

How do you keep the point order consistent across images?

Fix one corner dot as point 1 and walk the grid row by row; every image must return its points in that same order, and row k of the image points must pair with row k of the world points — anything else calibrates a lens that does not exist.

Symmetric grids hide the trap: a chart with equal dot counts on both axes looks identical after a 180° rotation, so the detector can silently hand you the rotated ordering on some frames. Three fixes, best first. Use a chart whose two axes carry different dot counts — the asymmetric layout stereo camera calibration with a circle grid target shows. Or put a fiducial mark or a missing dot in one corner. Or mask one corner dot with tape and treat the gap as the anchor. The symptom of a flipped frame is unmistakable: its reprojection error runs to many pixels while its neighbours sit near the mean.

Mind the coordinate origin while you order. Some pipelines put (0, 0) at the corner of the top-left pixel, others at its center, and MATLAB counts from 1 — mixing conventions offsets every point by half a pixel, the exact issue half-pixel offset in blob centroid: pixel coordinate origin untangles. And if the part offers only a handful of reference points instead of a dense grid, you are outside pattern calibration altogether; sparse reference point calibration: minimum points per model covers that route.

What is the full workflow from chart to parameters?

Eight steps, one afternoon: measure the chart, lock the camera, compute the geometry, capture 10–20 poses, detect, refine, order, estimate — then prune the worst image and estimate again.

  1. Measure the chart. Write the world points in millimetres from the measured pitch, in the fixed row order, and aim for at least 30 points per view; a 76 mm dot board supplies far more.
  2. Lock the camera. Manual exposure 5–10 ms, gain at minimum, aperture at f/8, focus set and taped so it cannot creep between poses. Save mono, uncompressed frames.
  3. Compute the geometry. Magnification, working distance and expected dot size in pixels, exactly as above, so the detector radius range is known before the first capture.
  4. Capture 10–20 poses. Chart filling 60–90% of the frame, tilts of 10–20° in four directions, every corner of the field visited, distances varied by ±20%. Moving the chart or moving the camera changes the error budget more than most engineers expect — camera calibration: move the camera or the chessboard? settles which.
  5. Detect. Run the imfindcircles pass, overlay the hits on one frame, and look at it before batching.
  6. Refine. Weighted centroid per dot from the code above; reject every dot whose patch touches an edge.
  7. Order. Anchor on the corner dot or fiducial, walk the rows, and stack the ordered points into a points-by-2-by-images array.
  8. Estimate and prune. Call the estimator, read the per-image errors, delete the worst image, run it again:
% imagePoints : numPoints x 2 x numImages, double, refined centers in pixels
% worldPoints : numPoints x 2, double, dot centers on the chart in millimetres
params = estimateCameraParameters(imagePoints, worldPoints);

Three views is the mathematical floor for a planar-target calibration; 10–20 views is what makes the distortion terms settle. Tell the estimator the image size and that the world units are millimetres, and switch on the extra radial and tangential terms for wide-angle lenses — those choices are name-value pairs on the same call.

How do you know the calibration is good enough?

Call it good under 0.5 px mean reprojection error: a careful dot-chart run lands at 0.2–0.3 px, and a mean above 0.7 px points at ordering or set-up problems long before it points at the lens.

Read the per-image errors, not just the mean. One frame at 3 px with the rest at 0.3 px is one dropped image — glare, a flipped order, a nudge of the focus ring. A mean near 0.8 px with no outlier means a systematic cause: points mis-ordered everywhere, a wavy printed chart, or dots imaged below 8 px. Change one thing, recalibrate, compare.

Then prove it physically. Take one extra image of a machined gap at a distance you did not calibrate at, remove the distortion with the parameters, and measure: agreement within about 1 px, at 23 µm per pixel in the example set-up, says the model holds where you will use it. Split the images in half, calibrate each half, and compare focal lengths; a repeat within a few tenths of a percent says the solution is stable. Last, the chart itself sits in the error chain — desktop-printed patterns move with humidity, and calibration target recertification: justifying a longer interval covers when a board still deserves trust.

When is a dot chart the wrong pattern?

Three cases say no: glossy charts that glare, scenes so wide the dots cannot reach 8 px, and any project where writing a detector buys nothing over the built-in checkerboard route.

Glare is the quiet one. A hot spot on a shiny dot pulls the weighted centroid toward itself, and no refinement fixes a biased mass — kill it with light, not code: a diffuse source, or crossed polarizers as cross polarization machine vision: reduce surface glare lays out.

When MATLAB is the only tool in the project and detector code feels like overhead, use a checkerboard: corner and centroid accuracy both land in the same 0.2–0.3 px band, so effort decides, not accuracy. Dot charts earn their keep when one target must serve calibration and production metrology at once, because dots are features you can keep measuring afterwards. If the working distance is fixed and the chart would image below about 8 px per dot, use a bigger chart or a longer focal length; sub-pixel centering cannot recover what the sensor never sampled.

What should you check before the first capture?

Two minutes down this list prevents almost every failed session: chart flat and measured, camera locked to manual, geometry computed, dots sized 8–30 px, capture plan written — all before the first frame.

  • Chart flat on a stiff backing, pitch measured with calipers, fiducial or asymmetric corner in place.
  • World points in millimetres, fixed row order, at least 30 of them.
  • Camera in mono, uncompressed output, manual exposure 5–10 ms, gain at minimum.
  • Aperture at f/8, focus set and taped; nothing automatic left running.
  • Geometry computed: dot size between 8 and 30 px at the working distance.
  • Chart on a stand or camera on a tripod; nothing will move mid-frame.
  • Capture plan written: 10–20 poses, tilts 10–20°, all four corners, ±20% distance.
  • Center overlay inspected on one frame; border dots rejected.

If the parts are what you still need, the accessories finder lists the boards and building a system bundles camera, lens and chart in one pass. Questions about a specific chart-and-camera pairing go to our contact page.

AccessoriesLens accessories

Adapters, tubes, prisms, targets

376 models · from $23.00

Questions

Is a checkerboard more accurate than a dot chart for MATLAB calibration?

On a careful set-up, no: both patterns land in the same 0.2–0.3 px band for mean reprojection error. A corner intersection and a round dot each refine to about a tenth of a pixel. The real difference is effort — the checkerboard detector is built in, the dot detector is your 30 lines of code. Choose dots when the same target must double as a metrology feature you measure in production images.

Can a stereo pair be calibrated from dot charts in MATLAB?

Yes. Detect and order the points in both cameras against the same world points, calibrate each camera on its own image set, then run the stereo estimation step with both image-point stacks; it returns the rigid transform between the cameras. Keep the chart fully visible to both cameras in every pose, or those frames drop out of the pair. Asymmetric dot layouts make the ordering unambiguous here.

Mean reprojection error sits at 0.8 px — where should you look first?

Per-image errors first: one frame at several pixels with the rest near 0.3 px is a dropped image — glare, blur or a flipped point order — so delete it and re-run. If every image sits near 0.8 px, work through causes in order: point order flipped on all frames, chart not flat, focus soft, dots imaged below 8 px. Change one thing at a time and recalibrate after each.

How big should the chart be relative to the field of view?

Plan the chart to span 60–90% of the frame's short axis at the working distance, and cover the field's corners with tilted poses rather than a bigger chart. A chart imaging far below that share leaves the edge distortion fitted by few points; a chart larger than the frame forces partial views, which only work when every clipped border dot is rejected. When the distance is fixed, choose the chart from the dot-size rule: 8–30 px per dot.

Does imfindcircles give sub-pixel centers on its own?

Plan on roughly a pixel of accuracy from that pass alone — its job is finding the dots, not finishing them. The weighted centroid in a patch around each hit is what takes the center to roughly 0.05–0.1 px. Skip the refinement and the scatter sits nearer 0.2–0.5 px, which flows straight into the mean reprojection error; on a 23 µm-per-pixel scene that is up to 12 µm of avoidable noise per point.