System designHow-to

Count lines per region automatically with blob analysis

Count lines per region automatically: threshold the fringe image, blob each region, and feed every bounding box to an edge counter that reports each count.

LumaSpec Vision12 min read Share on LinkedIn

On this page 12 sections
  1. 01What you need
  2. 02The pipeline: find regions first, count second
  3. 03Step 1: One fixed frame
  4. 04Step 2: Threshold at the valley
  5. 05Step 3: Close the lines into region blobs
  6. 06Step 4: Feed each bounding box to the counter
  7. 07Step 5: Verify the count
  8. 08Worked example: six regions on a 120 mm part
  9. 09Choosing camera and light
  10. 10When the count goes wrong
  11. 11Checklist before you build
  12. 12Questions

You have a fringe image: six patches of white lines, and you want one count per patch, every cycle, with nobody drawing search lines by hand. The standard pipeline does exactly that in three reusable stages: binarize, find each region with blob analysis, then feed every region's bounding box to an edge counter that reports its own line count. It runs anywhere that offers a particle or blob tool plus an ROI-driven line-profile detector: vision software on a PC at the bench, or the same two tools on a smart camera at the line. This guide walks the whole chain with numbers: pixel budget, lens focal length, light position, the two thresholds that decide success, and the checks that prove the count before you release it.

What you need

Three parts carry this job:

  • A camera with manual exposure and manual gain. Any model from the area scan cameras finder works once the pixel budget below is met; a global shutter matters only if the part or the fringes move during exposure.
  • Flat, diffuse illumination so the fringes, not the room, set the contrast. One bar light at 30-45° off-axis does it on matte prints.
  • Software with two tools: a particle (blob) analysis step that returns a bounding box per particle, and a line-profile or edge-detection step that accepts a region of interest. Every serious vision package and most smart cameras expose both.

For a bench build that grabs one frame per part:

Area scan camerasHikrobot MV-CU020-90GC 2.5 MP Area Scan Camera, GigE, GMAX4002, ColorMV-CU020-90GC
Sensor format
1/1.7"
Lens mount
C-mount
Interface
GigE
Resolution
Up to 3 MP
$309.00View partBuild a system with it

The MV-CU020-90GC is a 2.5 MP GigE camera with a global shutter, a 1/1.7-inch sensor and a C-mount. Its color sensor costs you nothing here: convert to gray before thresholding, or threshold the green channel, where the lens is sharpest.

On the light side:

Bar lightsBar light, 372 x 28 mm, White (LS-BAR-1276)LS-BAR-1276
Size
200-400 mm
Type
Diffused
Voltage
24 V
$439.00View partBuild a system with it

The LS-BAR-1276 is a diffused white bar, 372 x 28 mm, on 24 V. Set it 150-250 mm from the surface at 30-45° off the camera axis; that placement removes glossy-paper hot spots on most prints, and where it does not, cross-polarization machine vision finishes the job.

The pipeline: find regions first, count second

The order matters. Counting lines first and grouping them by position afterwards breaks the moment the part shifts a few millimetres. Reverse it:

  1. Grab one triggered frame with exposure and gain frozen.
  2. Threshold to a binary image at the histogram valley.
  3. Close the binary image so each region's lines merge into one particle.
  4. Run particle analysis; keep one bounding box (top, left, bottom, right) per region.
  5. For each particle, set the ROI from its box and count lines with a projected-profile peak count.
  6. Emit region index and count: Region 1 = 10 lines, Region 2 = 12, and so on.

The bounding boxes are recomputed every frame, so the regions track the part. That is the whole trick: the ROI is no longer a drawing, it is the output of the blob step. If your regions of interest ever point at the wrong image, read ROI image source binding: fix inspection region errors before touching thresholds; an ROI bound to a stale buffer looks exactly like a threshold failure.

Step 1: One fixed frame

Freeze the acquisition before you touch algorithms. Disable auto exposure and auto gain: an auto loop rebalances between regions of different brightness and drags the threshold with it, the failure mode behind auto exposure and auto gain on color cameras. Trigger one frame per part rather than free-running; the setup steps are in hardware trigger configuration per camera. Shroud the station so the LED is the only light source; then no 100 or 120 Hz mains ripple can modulate the fringes at any exposure.

Step 2: Threshold at the valley

Plot the gray-level histogram of one representative frame. Fringe images are bimodal: a background peak and a line peak. Set the threshold midway between the two peaks, or use the automatic between-class (Otsu) threshold your package offers; both land in the same valley. Never park a threshold on a peak's shoulder: a 10-gray-level move there swings measured line width by whole pixels. The mechanics of choosing that cut are in edge detection without a vision library: threshold basics.

Check the result once against physics. With 0.8 mm lines on a 2.0 mm period, white covers 0.8 / 2.0 = 40 % of a region; a binary image showing 55 % white is eating the gaps, so move the threshold toward the line peak.

Step 3: Close the lines into region blobs

At threshold, each white line is its own particle, dozens per region. Merge them with a morphological closing whose width bridges the widest gap inside a region but never the divider between regions:

closing width = 1.5 x widest gap inside a region

At the worked example's scale of 0.03 mm per pixel, a 1.2 mm gap is 40 pixels, so a 60-pixel closing merges the lines; the 7.5 mm divider is 250 pixels and stays open. Filter the particle list by area, keeping particles at least half the median region area, and dust specks vanish. Six particles remain, one per region, found with the same shape-level filtering you would use to detect a circle in a binary image with contour analysis and the same blob-then-decide logic as dark contaminant detection on dark surfaces.

Step 4: Feed each bounding box to the counter

Particle analysis returns, for every particle, its coordinates and extents: a bounding box with four edges, commonly reported as top, left, bottom and right. Convert that box into a rectangle ROI and inset it by 5 % per side; the outermost pixels of a region carry divider shadow and paper edge, and they corrupt the profile.

Inside the ROI, do not run one edge scan along a hand-placed line. Average instead: sum the ROI's columns when the fringes run vertically, and divide by the ROI width. You get a one-dimensional profile whose peaks are the lines. Averaging N pixels cuts random noise by about the square root of N, so 400 rows of averaging is a 20x noise reduction; that is why the projected profile holds up on grainy fringes where a single scan line stutters.

Count peaks, not raw transitions, when the background inside the region is uneven: a peak is a profile point above the midpoint of the profile's own minimum and maximum, separated from the last accepted peak by at least half the smallest fringe period. Each qualifying peak is one white line. If your region starts and ends in a dark gap, edge polarity is cleaner: count rising edges only, one per line. The one-dimensional run-length logic is the same math that counts barcode bars from an image. If you also need the fringe spacing, the same profile gives peak-to-peak distances; how precisely a peak can be located is covered in edge position accuracy from image sampling.

Blob tools return long records: coordinates, area, centroid, angle. Dump one particle and confirm which fields hold the box corners before wiring the loop, the same first move as debugging blob detection output.

Step 5: Verify the count

Prove the pipeline before the line sees it:

  1. Hand-count one known sample per region; all six must match.
  2. Cross-check with a second method: peak count versus center-line edge count, per region, must agree exactly.
  3. Run 100 frames of the same static part; every region's count must be constant to the last digit.
  4. Log the geometry: smallest line and smallest gap in pixels. Anything under 3 pixels is a merge waiting to happen.
  5. Sum the region counts and compare with a whole-image projection count taken between the dividers; the totals must match.

Check 5 fails loudly when two regions have merged: the blob count drops to five while the line total stays right. That is your alarm for Step 3's closing width.

Worked example: six regions on a 120 mm part

Take a 120 x 90 mm part carrying six fringe regions of 35 x 38 mm separated by 7.5 mm dividers. White lines are 0.8 mm wide on a 2.0 mm period, 0.8 mm line and 1.2 mm gap, so a 35 mm region holds about 35 / 2.0 = 17 lines.

Pixel budget. Four pixels across the narrowest feature is the working minimum; three is where counts start merging. At four pixels per 0.8 mm line, one pixel covers 0.2 mm of object:

pixel size on object = field of view / pixels across smallest feature in pixels = smallest feature / pixel size on object

120 / 0.2 = 600 pixels across and 90 / 0.2 = 450 down, so 0.27 MP is the floor. Anything from 2 MP up carries three times that with margin, which says plainly: in fringe counting the pipeline is the constraint, not resolution. Size your own part with the calculator:

Camera resolution for the smallest feature
Units
Pixels needed
–
Sensor size
– MP
Smallest sensor that fits
–
Pixel on the part
– mm
Pixels across the feature, that sensor
–

Pixels needed = field / feature × pixels per feature on each axis (field incl. margin). The lens must resolve the pixels too: Nyquist = 1000 / (2 × pixel µm) lp/mm.

Find cameras with enough pixels Open the full calculator

The LS-CMR-0166 outputs 4000 x 3000 pixels at 30 fps. Over the 120 mm field of view that is 0.03 mm per pixel, so the 0.8 mm lines land 27 pixels wide, the 1.2 mm gaps 40, and a full 2.0 mm period 67, nine times the minimum. The peak counter never sees a marginal fringe at that scale.

Lens. A 1/1.7-inch optical-format sensor is about 7.4 mm wide. Magnification and focal length follow:

m = sensor width / field of view width f = working distance x m / (1 + m)

m = 7.4 / 120 = 0.062. At a 430 mm working distance, f = 430 x 0.062 / 1.062 = 25.1 mm, so a 25 mm C-mount lens at roughly 430 mm covers the part. The estimate holds within a few percent; focus closes the rest. The lens focal length calculator runs the same two lines with your numbers.

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.

Light and exposure. One diffused white bar at 200 mm and 30-45° off-axis, exposure 5 ms, gain 0 dB, station shrouded. Five milliseconds sits far below the 8.3 ms ripple period of 120 Hz lighting, and with the LED as the only source the exposure length no longer changes the binary image. Run it and the six counts come out 17, 17, 16, 18, 17, 16; the sum, 101, matches the whole-image projection, so check 5 passes.

Choosing camera and light

Three builds cover nearly every fringe job:

  • Bench with a PC at the station: the MV-CU020-90GC shown above, 2.5 MP and global shutter on GigE.
  • Dense fringes or a bigger part: more pixels per fringe. The MV-CH120-11UC is a 12 MP USB3 camera with the IMX304 sensor and a global shutter, and its 1.1-inch sensor widens the field per lens.
Specification MV-CU020-90GC MV-CH120-11UC LS-CMR-0166
Sensor type CMOS, global shutter CMOS, global shutter –
Sensor model GMAX4002 Sony® IMX304 Sony IMX226
Pixel size 4 μm × 4 μm 3.45 μm × 3.45 μm 1.85 μm
Sensor size 1/1.7" 1.1" 1/1.7"
Resolution 2048 × 1200 4096 × 3000 4000 × 3000 (12MP)
Max. frame rate 49 fps @ 2048 × 1200 Bayer GB 8 30.3 fps @ 4096 × 3000 Bayer RG 8 30 fps
Dynamic range 66.9 dB 72.2 dB –
SNR 40.8 dB 40.2 dB –
Gain 0 dB to 11.1 dB 0 dB to 24 dB –
Exposure time 4 μs to 10 sec UltraShort exposure mode: 1 μs to 14 μs; Standard exposure mode: 15 μs to 10 sec –
Exposure mode Off/Once/Continuous exposure mode Off/Once/Continuous exposure mode –
Pixel format Bayer GB 8/10/10Packed/12/12Packed Mono 8/10/12; Bayer RG 8/10/10Packed/12/12Packed; YUV422Packed, YUV422_YUYV_Packed; RGB 8, BGR 8 –
Price $309.00 $2,339.00 · quoted $560.00

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

  • No PC at the line: run the same two tools on-device.
Smart cameras & vision sensorsHikrobot MV-SC3050XC-16M-ATN-H 5 MP color vision sensorMV-SC3050XC-16M-ATN-H
Interface
Fast Ethernet
Resolution
5 MP
Sensor format
1/1.45"
Shutter
Global
$1,809.00View part

The MV-SC3050XC-16M-ATN-H is a 5 MP vision sensor on Fast Ethernet with a global shutter; blob plus line-profile steps ship in that class of toolchain, and the counts ride out on Ethernet I/O.

On motion: the rolling-shutter LS-CMR-0166 suits this bench set-up, where the part is still during exposure. Put the part on a moving conveyor and a rolling shutter skews the lines, so there you want one of the global-shutter builds above.

When the count goes wrong

Four failure modes account for nearly every wrong number:

  • Two regions merge. Five particles instead of six, one box spanning two patches. Cause: a closing wider than the divider, or divider contrast below threshold. Fix: keep the divider at least 4x the widest intra-region gap, 7.5 mm against 1.2 mm here, and re-check the closing width.
  • Counts collapse to half. A region that hand-counts 17 reports 9. Cause: gaps under 3 pixels, so two lines fuse into one peak. Fix: shorten the working distance or step up sensor pixels; halving the pixel size on object doubles the pixels per gap.
  • The count flickers between frames. Cause: auto exposure or gain riding along, or a threshold on a histogram shoulder. Fix: freeze both, move the threshold to the valley, add 10 gray levels of hysteresis.
  • A glare streak reads as a line. On glossy prints a specular streak is a bright ridge exactly like a fringe. Fix: diffuse light off-axis, then cross-polarize if highlights remain.

Checklist before you build

  • Pixel budget: smallest line and gap at 4 pixels or more, sized with the calculator above.
  • Lens: f from m = sensor width / FOV at your working distance; 25 mm C-mount covers a 120 mm FOV near 430 mm.
  • Light: one diffuse bar at 30-45°, shrouded station, exposure and gain frozen, one frame per part on trigger.
  • Threshold: valley midpoint, 10 gray levels of hysteresis.
  • Closing: 1.5x the widest intra-region gap, divider 4x that gap.
  • Counter: profile midpoint peak rule, separation half the smallest period, ROI inset 5 %.
  • Proof: hand-count match, cross-method match, 100-frame stability, geometry logged, sum check equal to the whole-image projection.

Run your part's numbers first in the system configurator, or bring the fringe image to us through the contact page and we will size the chain with you.

Questions

Can I count the lines in every region without drawing a search line for each one?

Yes. That is exactly what the two-stage pipeline replaces: blob analysis recomputes each region's bounding box on every frame, and the box, not a drawing, sets the ROI for the counter. Draw one search line only while you hand-verify a sample; the production loop never uses one.

How many pixels do I need per fringe line?

Four pixels across the narrowest feature, the line or the gap, whichever is thinner, is the working minimum, and three is where two lines start fusing into one peak. For a 0.8 mm line on a 120 mm field of view that floor is 600 pixels across, 0.27 MP total; any 2 MP camera clears it several times over.

What if two regions merge into one blob?

Keep the physical divider between regions at least four times the widest gap inside a region, 7.5 mm against 1.2 mm in the worked example, and set the closing to 1.5 times the intra-region gap. Then rely on the sum check: the regions' counts must equal the whole-image projection count, and a merged pair drops the blob count to five while the line total stays right, which trips the alarm.

Do I need a global shutter camera for fringe counting?

Only if something moves during exposure. A static part on a bench images fine with a rolling shutter running at 30 fps. Once the part or the pattern moves, a conveyor, a vibrating surface, a live interferogram, a rolling shutter skews the lines and shifts counts; use a global shutter model there. Trigger one frame per part either way.

Why does the count change between identical frames?

Three usual causes, in order. Auto exposure or gain rebalancing between frames: freeze both. A threshold sitting on a histogram shoulder: move it to the valley and add 10 gray levels of hysteresis. Ambient light leaking past the shroud, which modulates at 100 or 120 Hz: shroud the station so the LED is the only source.

Can a smart camera do the per-region count without a PC?

Yes, if its toolchain has a blob tool that returns bounding boxes and a line-profile or edge tool that accepts an ROI input; most do. The loop runs on-device: six boxes in, six counts out over Ethernet I/O. Choose a PC camera instead when you want to archive every frame or reprocess history.