System designHow-to

Curve fitting a crack path in an image: fit and extrapolate safely

Curve fitting for a crack path in an image: extract the skeleton, scale pixels to millimetres, fit a quadratic against arclength, and keep extrapolation safe.

LumaSpec Vision11 min read Share on LinkedIn

On this page 9 sections
  1. 01How do you turn a crack mask into an ordered centerline?
  2. 02How do you convert skeleton pixels to millimetres?
  3. 03How much resolution does the crack need in the image?
  4. 04Which curve should you fit, and against which variable?
  5. 05How do you choose the polynomial order without chasing noise?
  6. 06How far past the crack tip can you extrapolate?
  7. 07When does the fitted path lie to you?
  8. 08What is the full procedure, end to end?
  9. 09Questions

You have a crack mask and you need numbers: a smooth path in millimetres along the crack, and an honest estimate of where the tip runs next. The pipeline is segment, clean, skeletonize, order, scale, fit, extrapolate. Every stage carries a number you can check. This how-to runs a 300 mm wall crack imaged at 2.5 px/mm with a 12 MP camera as its worked example, so you can recompute each figure against your own images before trusting a predicted tip on real concrete.

How do you turn a crack mask into an ordered centerline?

Threshold or segment the crack, thin the mask to a one-pixel skeleton, then walk the skeleton from one endpoint to the other to order the pixels. At a branch point, where a pixel has three or more neighbours, split the path and treat each branch as its own curve.

Endpoints are skeleton pixels with exactly one neighbour; branch points have three or more. From one endpoint, walk pixel to pixel and record each (column, row) pair — that ordered list is what you fit. When the crack forks, walk each branch on its own. A Euclidean graph with branch points as nodes and branches as edges describes the whole pattern while keeping every branch a single ordered path.

Clean the mask before thinning. Remove connected components below about 20 px². At 2.5 px/mm a speck 2 mm across spans roughly 5 px, which is about 20 px² of area, so this cutoff drops pores and shadows before they turn the skeleton into a hairball.

Keep two lengths apart. Path length is the sum of pixel steps along the skeleton and it feeds the fit; endpoint distance is the straight line between tips and answers other questions, such as spacing between two cracks.

How do you convert skeleton pixels to millimetres?

Calibrate scale in the crack's own plane: image a ruler or two known points there, then pixels per millimetre equals the known distance divided by the measured pixel count. In the worked example, 500 px across a 200 mm rule gives 2.5 px/mm, or 0.4 mm per pixel.

Place the rule on the wall, square to the camera, in the same plane as the crack; anything nearer or farther carries a different scale. Check with a second pair of marks elsewhere in the frame. At 2.5 px/mm a 100 mm gap should measure 250 px, and agreement within ±2.5 px (1%) says the scale holds.

px_per_mm = known_mm / measured_px mm_per_px = 1 / px_per_mm s_i = s_(i-1) + sqrt(dx^2 + dy^2) × mm_per_px band(d) = RMS × (1 + d/L)^2

Watch tilt. A surface leaning 5° from parallel shortens distances by cos 5° = 0.996, a 0.4% error; at 10° it is cos 10° = 0.985, or 1.5%. Shoot within about 5° of square or correct the geometry. When you cannot reach the wall to place a rule, four known points on the surface define the pixel-to-plane mapping, as in ground-plane pose from four known points; this is the same calibration that turns defect pixel coordinates into real positions.

On a stage, for coupon-sized specimens, make the scale an optical property instead of a target. A fixed-magnification lens sets it once and holds it: the LS-TCL-0574 delivers 0.4x magnification at a 227 mm working distance on a 1.2" sensor through a C-mount. Mount the camera on a rigid camera stand so the magnification stays put between shots.

Machine vision lensesFixed-magnification lens, 0.4x, 227 mm WD, 1.2" (LS-TCL-0574)LS-TCL-0574
Sensor format
1.2"
Mount
C-mount
Image circle
16-22 mm
$2,269.00View partBuild a system with it

How much resolution does the crack need in the image?

Plan for at least 2 px per millimetre on the crack, which keeps the visible width at several pixels and holds skeleton jitter near 0.5 mm. The worked example needs 750 px of crack, so a 4000-column sensor covers it with room to spare.

The number that decides accuracy is tip localization. The skeleton tip sits within ±2 px, and scale converts that — ±0.8 mm at 2.5 px/mm, ±1 mm at 2 px/mm. Below about 2 px/mm the crack thins toward one pixel, thresholds turn unstable and the skeleton wanders.

Size the field from the crack, not the wall. The example crack is 300 mm and we want it to span 750 px: 750 px ÷ 300 mm = 2.5 px/mm, so the image width must cover 4000 px × 0.4 mm/px = 1600 mm of wall. The worked example uses the LS-CMR-0166, a 12 MP USB3 camera whose IMX226 sensor delivers 4000 × 3000 pixels on a 1/1.7" format with a rolling shutter.

A 1/1.7" sensor is about 7.4 mm wide, so magnification m = 7.4 / 1600 = 0.0046. The lens relation f = WD × m / (1 + m) gives f = 2000 × 0.0046 / 1.0046 ≈ 9 mm at a 2 m working distance, and f scales directly with working distance. Check your own numbers here, then pick from the area scan cameras in the camera finder.

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

For longer cracks, the same px/mm with more columns wins. The MV-CS200-10UM is a 20 MP mono USB3.0 camera on a 1" sensor with a C-mount, and mono reads grey-on-grey crack contrast without Bayer interpolation.

Specification LS-CMR-0166 MV-CS200-10UM
Sensor model Sony IMX226 Sony® IMX183
Resolution 4000 × 3000 (12MP) 5472 × 3648
Max. frame rate 30 fps 19.2 fps @ 5472 × 3648 Mono 8
Pixel size 1.85 μm 2.4 μm × 2.4 μm
Sensor size 1/1.7" 1"
Data interface USB 3.0 USB3.0, compatible with USB2.0
Price $560.00 $759.00

Values as printed in each product's data sheet; open a part for its drawing and full specifications.

Which curve should you fit, and against which variable?

Fit each coordinate against arclength, not y against x. With x(s) and y(s) as two separate low-order polynomials the curve follows any orientation, and a quadratic — degree 2 — is usually enough for a gently curved crack.

Fitting y as a function of x breaks the moment the crack turns steep or vertical, because one x then carries several y values. Arclength fixes that: compute s along the skeleton in millimetres and fit x(s) and y(s) independently. These are two ordinary least-squares problems, no special algorithm.

Both fits run on documented library calls: numpy.polyfit returns coefficients with the highest power first. For a wiggly path, scipy.interpolate.UnivariateSpline with k=3 and a smoothing factor handles the curvature without forcing one stiff polynomial through it.

import numpy as np

# Illustrative inputs from the skeleton, all float64, shape (750,):
# s_mm = arclength in mm, x_mm and y_mm = crack coordinates in mm
cx = np.polyfit(s_mm, x_mm, 2)      # highest power first
cy = np.polyfit(s_mm, y_mm, 2)
rms_mm = float(np.sqrt(np.mean((np.polyval(cx, s_mm) - x_mm) ** 2)))
assert rms_mm < 0.5                  # worked example: 0.16 mm
tip = (np.polyval(cx, s_mm[-1] + 60.0),
       np.polyval(cy, s_mm[-1] + 60.0))

How do you choose the polynomial order without chasing noise?

Fit degrees 1 to 3, compare RMS residuals, and keep the lowest degree whose residual stops falling by more than about 20% when you add one. For most concrete cracks that lands on the quadratic, with the residual under one pixel.

The worked example tells the story. A straight line leaves 1.8 px RMS, which means the curvature is real. Degree 2 drops the residual to 0.4 px, an improvement of (1.8 − 0.4) / 1.8 = 78%, so take the degree. Degree 3 manages 0.39 px: (0.4 − 0.39) / 0.4 = 2.5%, which is noise, so stop.

Extra degrees always fit the inside of the span better and predict the outside worse. High-order terms swing violently outside the data, and the extrapolation you want is the first thing they wreck. A genuine S-bend takes degree 3, or a split at the inflection point; a path that wiggles along its whole length takes the smoothing spline, kept inside the measured span.

How far past the crack tip can you extrapolate?

Keep extrapolation to 10–20% of the fitted span beyond the measured end. A quadratic's prediction error grows roughly with the square of the distance from the data, so reaching 20% past the tip widens the band by (1 + 0.20)² ≈ 1.44×.

The mechanism is the curvature term. In a least-squares quadratic, uncertainty in the quadratic coefficient dominates away from the data and enters the prediction multiplied by the square of the distance, so the band scales as RMS × (1 + d/L)², with d the reach past the tip and L the fitted span.

Reach past the tip d Band multiplier (1 + d/L)²
10% of L (1.10)² = 1.21
20% of L (1.20)² = 1.44
50% of L (1.50)² = 2.25
100% of L (2.00)² = 4.00

Run the worked example. The residual is 0.4 px = 0.16 mm; extrapolating d = 0.20 × 300 = 60 mm widens the band to 0.16 × 1.44 = 0.23 mm. Tip detection adds ±2 px = ±0.8 mm, and combined uncertainty is √(0.23² + 0.80²) ≈ 0.8 mm — the skeleton endpoint, not the fit, dominates. Direction matters too: a 2° error in tip direction swings a 60 mm reach sideways by 60 × tan 2° ≈ 2.1 mm, which is why you mark a band, not a point.

Extending shape is not predicting growth. Where the crack runs next follows from its current curvature; how fast it grows needs repeat inspections — crack growth from image sequences fits tip position against time instead. And the extension assumes the crack keeps its curvature past the tip; a kink or a branch invalidates it, and no polynomial can warn you first.

When does the fitted path lie to you?

Distortion and tilt corrupt geometry before any fit: 0.3% lens distortion bends the edge of a 1600 mm field by 0.003 × 800 = 2.4 mm — fifteen times the 0.16 mm residual — so calibrate the lens or keep the crack in the central half.

Radial distortion grows toward the image edge, and the half-field here is 800 mm, so a 0.3% rating is worth about 2.4 mm of sideways shift at the border — the entire error budget, twice over. Two defences work: calibrate the lens with a checkerboard and undistort before fitting, or compose so the crack stays inside the middle half of the frame. A low-distortion fixed lens keeps the geometry honest by construction: the LS-FFL-0567 is a 16 mm C-mount lens rated for 20 MP on 1.1" sensors, with F2.8-22 and <0.3% distortion. Once your focal length is set, browse the machine vision lenses in the lens finder.

Machine vision lenses16 mm, 1.1", 20 MP, C-mount machine vision lens, F2.8-22, <0.3% distortion (LS-FFL-0567)LS-FFL-0567
Type
Machine vision fixed
Sensor format
1.1"
Mount
C-mount
Resolution
16-25 MP
$679.00View partBuild a system with it

Then there is concrete itself. Dark veins, damp patches and formwork marks pass a naive threshold; the area filter removes the specks, and a continuity check removes the rest. A real crack forms one connected path — skeleton pieces that start and end in the middle of nowhere are dropped before the fit sees them.

What is the full procedure, end to end?

Run the same eight steps every inspection — capture with a scale target, segment, clean by area, skeletonize, order or graph, fit degree 2–3 against arclength, report residual and band, then extrapolate at most 20% — so results from different visits stay comparable.

  1. Place a ruler or two coded targets in the crack plane and shoot square to the wall, within 5° of parallel.
  2. Segment the crack: threshold, edge following or a trained segmenter, whichever holds on your surface.
  3. Remove connected components below 20 px² so pores and specks never reach the skeleton.
  4. Skeletonize to one pixel and tag endpoints (one neighbour) and branch points (three or more).
  5. Walk each branch to order its pixels; convert to millimetres and compute arclength s.
  6. Fit x(s) and y(s) at degrees 1–3 and keep the elbow degree — quadratic at 0.4 px RMS here.
  7. Report crack length, RMS residual in millimetres and the extrapolation band from the (1 + d/L)² table.
  8. Extend at most 20% of the span — 60 mm here — and mark the predicted tip at ±1 mm for the next visit.

Verify before you file the result: the overlay hugs the skeleton within about 1 px, the scale pair re-measures at 250 px ± 2.5, and a second image of the same crack from a slightly different position predicts a tip within about ±1 mm of the first.

To size the camera, lens and working distance for the pixel scale your crack needs, the configurator below starts from the camera and walks forward. The systems topic page collects the related measurement guides, and the contact page is the route for curved or hard-to-reach surfaces where the scale calibration changes.

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

Can curve fitting tell me when a crack will grow?

No. The fit extends the crack's shape in space, not in time. Growth rate needs repeat inspections with the same scale, viewing angle and lighting, so tip positions from different visits are comparable; you then fit tip position against date. That time trend is a separate regression with its own residuals — treat it as its own study, on its own graph.

What changes when the crack branches?

Treat the skeleton as a graph. Branch points become nodes and each branch becomes an edge that you fit on its own arclength. Report a predicted tip per branch, and get total crack length by summing the branch lengths. Never fit one polynomial across a branch point: the path is not a single curve there and the fit will cut the corner.

Which Python functions fit and extend the curve?

numpy.polyfit(s_mm, x_mm, 2) returns least-squares coefficients with the highest power first, and np.polyval evaluates them past the last point. For a wiggly path, scipy.interpolate.UnivariateSpline with k=3 and a smoothing factor s is easier than forcing one high-degree polynomial through the data. Splines track shape well but extrapolate poorly, so keep them inside the measured span.

How accurate is the fitted crack length?

In the worked example: 0.16 mm of fit residual, ±0.8 mm of tip detection (2 px at 0.4 mm/px) and roughly 0.5% scale uncertainty. The scale term grows with length: 300 mm × 0.5% = 1.5 mm, so quote the length as 300 ± 2 mm. Tip position uncertainty stays near ±1 mm no matter how long the crack is.

Does this work on photos taken from farther away, such as from a drone?

Yes, if a scale target sits in the crack plane and the camera points squarely at the wall. Tilt shrinks distances by the cosine of the angle: 10° costs about 1.5%. Wide-angle lenses add distortion that must be calibrated out, and accuracy drops in proportion to the larger mm-per-pixel value.