3D visionHow-to

Surface area of holes in a segmented 3D image

Measure the surface area of holes in a segmented 3D image: closing with a sized element, voxel-face counting and the spacing arithmetic, plus a worked example.

LumaSpec Vision11 min read Share on LinkedIn

On this page 10 sections
  1. 01What counts as the surface area of a hole in a segmented 3D image?
  2. 02How does morphological closing seal a crack?
  3. 03How big should the structuring element be?
  4. 04How do you compute the area step by step?
  5. 05What does the arithmetic look like on real numbers?
  6. 06Why does the difference map include regions you never circled?
  7. 07How accurate is the voxel-face number?
  8. 08When does a height map beat a voxel volume?
  9. 09Which 3D sensor captures images this method works on?
  10. 10Questions

You segmented a particle in a 3D image, and the holes on its surface — the cracks that let the interior void open to the outside — need a number: an area in mm², not a red circle on a render. This guide gives you that number. You will seal each opening with a morphological closing sized to the crack, isolate the plug the closing creates, and convert voxel faces to square millimetres with your grid spacing. The same steps work on micro-CT volumes, structured-light scans and stacked laser profiles, and they end with a per-crack area table you can drop straight into a report.

What counts as the surface area of a hole in a segmented 3D image?

The area you want is the count of voxel faces where the crack plug meets the outside background, multiplied by the face area of your grid: at 2 mm isotropic spacing that is 2 mm × 2 mm = 4 mm² per exposed face.

Call the region the closing adds the plug. For the openings you circled, the plug is a thin cap sitting in the mouth of the crack. Two face counts are worth having. Faces between the plug and the exterior background give the mouth area — the number a feeler gauge would confirm. Faces between the plug and the interior void give the crack's inner wall. On a straight through-hole the two mouths come out near enough equal, so decide once whether you report a single mouth (divide by two) or the whole plug surface, and stay consistent across the part family.

How does morphological closing seal a crack?

Closing dilates the segmentation with a structuring element and erodes it back, sealing every opening narrower than about twice the element's radius: a ball of radius 4 voxels bridges gaps up to roughly 8 voxels across.

The bridge survives the erosion, because once the dilated solid spans the gap there is no background left in the channel for the erosion to reopen. Subtracting the original mask from the closed mask leaves exactly the added material — the plugs and nothing else. The closing you already tried (imclose and its equivalents in other libraries) was the right operator. What it lacks on its own is selection: the raw difference contains every narrow dent and rim fold on the particle, and a fill-holes routine would not help either, because it swallows any enclosed void no matter how the opening compares to your crack. The filter that keeps only crack plugs comes a few sections down; first, size the element.

How big should the structuring element be?

Measure the widest opening on a cross-section, then set the ball radius just above half of it: a crack 7 voxels across needs a radius of 4 voxels, because a spherical element seals gaps up to about twice its radius.

Measure the width on the slice where the mouth is widest, or from the distance map of the background inside the channel. A radius below half the widest opening leaves that crack unsealed, and the difference map simply will not contain its plug — the failure mode behind a closing that seems not helpful. A radius far above it starts flooding genuine concavities and pads the mouth rim, which inflates the very area you are about to report.

How do you compute the area step by step?

Six operations take you from segmented volume to a per-crack area table: voxelize at known spacing, segment, label the interior void, close with the chosen ball, keep the plug components that touch that void, then multiply exposed faces by the face area.

You need the binary segmented volume, its spacing, and a toolkit with closing, connected-component labeling and a face counter. ITK-based stacks ship the closing as BinaryMorphologicalClosingImageFilter; MorphoLibJ provides the same operations for ImageJ stacks. Then:

  1. Voxelize the data at a spacing you control and record Δx, Δy, Δz. Starting from a point cloud? Grid it deliberately — the point-cloud voxel grid guide covers the choices that distort later counts.
  2. Segment the particle into a binary mask, and check on a few slices that the surface follows the part, not the noise.
  3. Label the background. Components that reach the volume border are exterior; enclosed components are interior voids. No void means there is nothing to seal — every hole already opens to the outside as a dent.
  4. Compute the closed mask with the ball from the previous section, then form the difference: closed minus original.
  5. Connected-component the difference. Keep components that touch both an interior void and the exterior background, and whose mean thickness (volume ÷ exposed face area) is a few voxels or less. Label each kept component as one crack plug.
  6. For each plug, count faces to the exterior background and faces to the interior void, multiply by the face areas from the next section, and halve the exterior count for a straight through-hole if you report one mouth.

Verify before trusting the table: overlay the plugs on the original slices. Each plug should sit in the mouth like the cap you would have drawn by hand, roughly where your red circles were.

What does the arithmetic look like on real numbers?

At 2 mm isotropic spacing, a plug of 1,240 voxels with 620 exterior-facing faces has a mouth area of 620 × 4 mm² = 2,480 mm² and a mean thickness of 4 mm, which is the thin cap you expect.

a_face = Δx × Δy (top faces; side faces use Δy × Δz or Δz × Δx) A_mouth = N_faces_ext × a_face V_plug = N_voxels × Δx × Δy × Δz t_mean = V_plug / A_plug

Worked example, with the arithmetic in full. A sintered pellet is scanned with Δx = Δy = Δz = 2 mm, so a face is 2 mm × 2 mm = 4 mm² and a voxel is 8 mm³. The widest crack opening measures 7 voxels on the slice, so the ball radius is 4 voxels. The closing adds a difference map; one component touches both the interior void and the exterior, with 1,240 voxels and 620 faces looking out at the exterior background:

  • Mouth area: A = 620 × 4 mm² = 2,480 mm², which is 24.8 cm².
  • Cross-check: the exterior faces form a band roughly 177 mm long and 14 mm across, and 177 mm × 14 mm = 2,478 mm² — matching the face count within discretization.
  • Plug volume: V = 1,240 × 8 mm³ = 9,920 mm³.
  • Mean thickness: t = 9,920 mm³ ÷ 2,480 mm² = 4 mm, two voxels — a cap rather than a lump, so it passes the thickness guard in step 5.
  • Straight through-hole in a 30 mm wall: report one mouth as 2,480 mm² ÷ 2 = 1,240 mm².

The same spacing arithmetic gives volumes for whole regions; the voxel spacing volume calculation runs it on segmented volumes end to end.

Why does the difference map include regions you never circled?

Closing bridges every narrow gap and smooth dent it meets, so on a rough particle the raw difference can hold dozens of components; only those touching a labeled interior void are crack plugs — in the worked example that filter kept 1 component out of 27.

The rejects have a pattern. Concavity fills touch only the exterior background, because a dent never encloses a void, so the void test in step 5 removes them without tuning. The thickness guard then catches what remains: a broad smooth recess leaves a shallow bowl of added voxels whose exposed area dwarfs its volume. What the filters cannot tell apart is a real crack and a capture dropout — an area where the sensor returned no points at all. Check the raw depth before measuring: a dropout has no measurements, a crack has wrong-looking ones, and the missing points in a point cloud guide walks through how depth holes form and when to mask them instead of measuring them.

How accurate is the voxel-face number?

Face counting is an upper bound: on a wall at 45° the staircase of voxel faces covers twice the projected area while the true surface covers 1.41× that projection, so the count runs about 41% high there, and less on steeper or shallower walls.

Three ways to tighten it. Run marching cubes on the plug surface and measure the mesh: on surfaces smooth at voxel scale the mesh lands within a few percent of the true area, and it never stair-steps. Keep voxels small relative to the crack — the rule in the last section, 5 or more voxels across the narrowest crack, also keeps this bias from dominating. Respect anisotropy: a stretched grid stretches side faces too, so count faces per direction and multiply by that direction's face area, exactly as the formula block allows. Where stretched spacing comes from, and how to prevent it, is the subject of the scan spacing guide for laser triangulation; the per-axis scale factor method for depth images shows the corrections when the grid is already stretched.

When does a height map beat a voxel volume?

If the sensor sees one side only, work on the height map: segment the crack footprint in the depth image and multiply its pixel count by the pixel pitch — 0.05 mm pixels give 0.05 mm × 0.05 mm = 0.0025 mm² per pixel — and skip 3D closing entirely.

The crack mouth lies flat on the scanned face, so its projected area is the number you want, and pixel counting delivers it with no face bookkeeping. The closing-difference trick still applies, now in 2D: close the footprint mask, subtract, and each remaining blob is one opening. At that same 0.05 mm pitch, a 400-pixel footprint is 400 × 0.0025 mm² = 1 mm². Two things a single-sided map cannot give you: interior voids (a crack into a hidden pocket shows only its mouth) and true wall areas. Depth alongside the footprint helps grade severity — the height difference method for point clouds measures how far the surface sits below nominal. And when the same part returns scan after scan, each footprint feeds straight into crack growth measurement from image sequences.

Which 3D sensor captures images this method works on?

Match the sensor to the crack, not the part: the narrowest crack you must measure should span at least 5 voxels or pixels in the raw data, because a crack 2 pixels wide vanishes into segmentation noise.

Two sensor classes cover the cases in this guide. Laser profile sensors return a height value for every x-y position on the part — exactly the height-map input the previous section wants. The profiler below is a typical pick for that job.

3D sensorsHikrobot MV-DP4180-03P 3D Laser Profile SensorMV-DP4180-03P
Type
Laser profiler
$12,389.00 · quotedView and quote

When the measurement needs the closed volume — interior voids, through-cracks, plug volumes — a projected structured-light camera captures that shape directly. The camera below is that class of sensor.

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

Laser profilers and stereo 3D cameras

170 models · from $699.00

To size either class against your part, set the spacing you need in the 3D camera finder or work through the camera configurator; more voxel-level methods sit on the 3D inspection topic page. If you send the part size and the narrowest crack width through the contact page, we will check the voxel budget against the crack with you before you order.

Questions

Does the same closing trick work on a 2D image?

Yes, and it is simpler. Close the footprint mask with a disc, subtract the original, and each blob in the difference is one opening; its area is the pixel count times the pixel pitch, with no face counting. The radius rule carries over: a disc of radius r seals openings narrower than about 2r pixels, so measure the widest crack and pick the radius just above half of it.

What structuring element shape should I use?

A ball, or a close approximation of one. A ball seals the same width in every direction, while a cube of radius r bridges diagonal gaps up to about 2r√3 — roughly 73% wider than the 2r you sized for — so cracks you meant to leave open can get sealed from a corner direction. Most libraries approximate the ball acceptably at these sizes; check the element's diagonal reach if in doubt.

How do I handle voxels that are not cubes?

Give each direction its own face area. With Δx = 0.05 mm, Δy = 0.05 mm and Δz = 0.2 mm, a top face is 0.0025 mm² and a side face is 0.01 mm². Count the plug's exposed faces per direction, multiply each count by its face area, and add the products — summing one global face area is what turns stretched grids into wrong areas.

Can I report the crack volume too?

Yes — plug volume is the voxel count times the voxel volume. In the worked example that is 1,240 voxels × 8 mm³ = 9,920 mm³, about 9.9 cm³. Mouth area and plug volume together separate a shallow pit (large area, small volume) from a deep channel (small mouth, large volume), which is usually the distinction an inspection report actually needs.