System designHow-to

Detect screw orientation angle and level the image

Detect a screw's orientation angle from an image: fit a line along the axis or sweep a Radon projection, rotate by the opposite angle to level it.

LumaSpec Vision10 min read Share on LinkedIn

On this page 10 sections
  1. 01What you need
  2. 02Size the field of view first
  3. 03Step 1: Pick points along the screw axis
  4. 04Step 2: Fit the slope and convert it to degrees
  5. 05Step 3: Rotate by the opposite angle
  6. 06Step 4: Verify the leveled image, then accept or iterate
  7. 07Radon alternative: sweep projections and take the peak
  8. 08What the accuracy is made of
  9. 09Common mistakes
  10. 10Questions

A screw that arrives five degrees off horizontal breaks every step downstream: templates miss, a measured length reads 0.4% short at 5° of tilt, and a picker grips across the wrong axis. The fix is two numbers and one transform. You measure the orientation angle of the screw's axis in the image, rotate the image by the opposite angle, and verify the leveled result with a second fit. This guide shows both ways to get the angle — a least-squares line fit through points along the axis, and a Radon projection sweep that needs no threshold — plus the sign conventions, the acceptance threshold and the field-of-view math that decide whether the leveled image can be trusted. The whole loop runs offline on a static frame or on-device in a smart camera, in tens of milliseconds per image.

What you need

Start from one static grayscale frame where the screw is a single elongated object on a contrasting background. Backlight through a flat glass plate gives the cleanest shank silhouette; a directional bar raked low across the part also works. Diffuse ring glare on polished steel is the problem — bright blobs ride the thread crests and drag fitted points off the axis.

The camera side is ordinary. Put at least 1,000 px on the screw's length; 2,000 px is comfortable. For a 60 mm screw imaged at 300 mm working distance, a 35 mm lens on a 2/3" format sensor fills the frame. The LS-FFL-0679 is a 35 mm C-mount lens rated for 6 MP on 2/3" sensors.

Machine vision lenses35 mm, 2/3", 6 MP, C-mount machine vision lens (LS-FFL-0679)LS-FFL-0679
Type
Machine vision fixed
Sensor format
2/3"
Mount
C-mount
Resolution
6-10 MP
$219.00View partBuild a system with it

A 6 MP mono sensor then lands the example's pixel scale near 30 µm/px. The MV-SC5060XM-08M-WBN is a 6 MP mono smart camera with an M12 mount and a GigE interface, so the whole fit-and-rotate loop runs on the device with no PC in the loop.

Smart cameras & vision sensorsHikrobot MV-SC5060XM-08M-WBN SC5000X series Smart Camera, 6 MP, Mono, 8 mm focal length, M12-mountMV-SC5060XM-08M-WBN
Interface
GigE
Resolution
6-10 MP
Sensor format
1/2.4"
Shutter
Rolling
$1,629.00View part

Vision sensors carry the same loop at lower resolution. The MV-SC3050XC-16M-ATN-H is a 5 MP color vision sensor with a global shutter, and the HK-TD032-12-WBN is a 1.6 MP mono vision sensor — both Fast Ethernet with M12 mounts.

Smart cameras & vision sensorsHikrobot MV-SC3050XC-16M-ATN-H 5 MP color vision sensorMV-SC3050XC-16M-ATN-H
Interface
Fast Ethernet
Resolution
5 MP
$1,809.00View part
Smart cameras & vision sensorsHikrobot HK-TD032-12-WBN 1.6 MP mono vision sensorHK-TD032-12-WBN
Interface
Fast Ethernet
Resolution
Up to 3 MP
$1,699.00View part

Browse the machine vision lenses by sensor format and focal length, the smart cameras by resolution and interface, or backlight panels and directional bars in the light finder.

Size the field of view first

The arithmetic that decides whether the leveled image still holds the whole part:

FOV = WD × sensor width / focal length pixel scale = pixel pitch × WD / focal length

Take a 2448 × 2048 px sensor with 3.45 µm pitch as the example camera, so the sensor is 8.45 mm wide. With the 35 mm lens at 300 mm working distance:

  • FOV width: 300 mm × 8.45 mm / 35 mm = 72.4 mm
  • Pixel scale: 3.45 µm × 300 / 35 = 29.6 µm/px
  • A 60 mm screw spans 60,000 µm / 29.6 µm ≈ 2,029 px

Rotation then costs corners. Leveling this 72.4 × 60.6 mm frame through 5° keeps only the largest axis-aligned rectangle inside the rotated bounds: about 2,260 × 1,827 px, or 66.8 × 54.0 mm. The screw has to fit that smaller rectangle, so leave about 10% of width margin when you size the field — here 66.8 mm still clears the 60 mm part by 6.8 mm.

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

The same pixel-scale arithmetic worked from magnification instead of working distance is in calculate object space pixel size from magnification.

Step 1: Pick points along the screw axis

  1. Crop a tight ROI around the screw. Fixture edges, rail lines and background print all contribute points that tilt a least-squares fit.
  2. Harvest axis points. On a backlit silhouette, threshold and take the centroid of each column of the part — one axis point per column, around 2,000 for the example screw. On grayscale without a clean silhouette, a corner detector such as detectHarrisFeatures finds thread-root and shank-edge corners directly.
  3. Prefer shank points, or spread points over many thread pitches. Points riding one coarse-thread crest follow the projected crest wave, not the axis.
  4. Fit once, drop points with residuals beyond 2 px, fit again. A single outlier 10 px off the line visibly tilts a 200-point fit; two trimming passes are normally enough.
  5. Target 200 or more points across the full length. The feature-not-whole-part logic from teaching long thin parts to a vision system by feature applies unchanged: the axis is the message, not the outline.

Step 2: Fit the slope and convert it to degrees

Least squares through the points gives a slope; arctan turns it into degrees:

m = Σ(xᵢ − x̄)(yᵢ − ȳ) / Σ(xᵢ − x̄)² θ = arctan(m)

Using only the two endpoints instead of a full fit? Take θ = arctan2(Δy, Δx), so a near-vertical axis never divides by zero.

Worked example: the fit across 2,029 px of screw returns m = 0.0875, so θ = arctan(0.0875) = 5.0° — tan 5° is 0.08749. In pixels the shank drops 0.0875 × 2,029 ≈ 178 px from head end to tip.

Image rows count downward, so a positive slope means the right end of the screw hangs low on screen. Fix the acceptance threshold now, before rotating: tan 0.1° = 0.001745, so a refit slope under 0.0017 reads as level at 0.1°.

Step 3: Rotate by the opposite angle

With rows growing downward, a positive fitted slope needs a counterclockwise rotation of +θ — a call like imrotate(img, angle) with the fitted angle does exactly this. If your library turns clockwise for positive angles, pass −θ. If the convention is unclear, rotate the first part both ways and keep the sign whose refit is flatter.

Then choose what rotates:

  • The pixels, when the leveled image is the product — display, archive, or the input to a template match. Bilinear interpolation keeps edges usable but softer.
  • The point coordinates by −θ, when anything downstream still measures. Measure on the original frame, rotate the coordinates, quote the rotated values.

Remember the corner crop from the sizing section: at 5°, the example frame survives as 66.8 × 54.0 mm. The mechanics and interpolation trade-offs are detailed in arbitrary angle image rotation in machine vision, and if the station reads the part vertically instead, rotate a camera image 90 degrees before measurement covers the fixed-angle case.

Step 4: Verify the leveled image, then accept or iterate

Refit on the output. The example's second fit reads a residual slope of 0.0008, and arctan(0.0008) = 0.046°, under the 0.1° threshold: pass. A residual between 0.1° and 0.5° deserves one more iteration with the extra angle added; anything larger means the first fit latched onto the wrong feature, so clean the ROI and restart at Step 1.

Two checks belong in every acceptance:

  • Head versus tip. A bare axis looks identical under a 180° flip, and a downstream match that flips the part makes mirror-image false hits — the failure mode dissected in pattern match flips 180 degrees. Settle the ends with a feature check: head diameter against shank diameter, or the chamfer blob at the tip.
  • Rotation with shift or scale. If the part also translates or the FOV drifts between shots, one combined search beats separate corrections; rotation and scale affine transform search in machine vision works through it.

Feeding a picker? The angle you accept has to sit inside the gripper's orientation tolerance, which is its own matching problem — see symmetric part orientation matching.

Radon alternative: sweep projections and take the peak

When the silhouette is unreliable — polished parts on a reflective tray, low contrast, cluttered background — skip segmentation. The Radon transform projects image intensity along a list of angles, one output column per angle, and a bright elongated part piles its brightness into the column at its own angle. The brightest column is the tilt.

A sensible sweep for a screw expected within ±10° of horizontal:

  • First pass: θ from −10° to +10° in 0.1° steps, 201 columns. The peak column reads the angle at 0.1° resolution.
  • Refine: a second sweep of ±0.2° around the peak in 0.02° steps — 21 columns — or fit a parabola through the peak column and its two neighbors for a sub-step estimate.

Cost scales with columns times pixels, so keep the ROI tight and the sweep range near the fixture nominal. A known ±10° does not need a 0° to 180° scan.

What the accuracy is made of

Two budgets add up, and the systematic one dominates.

Random error comes from point scatter: σθ ≈ arctan(σp / L), with σp the perpendicular scatter and L the baseline. The example's 0.5 px of scatter over 2,029 px gives arctan(0.5 / 2029) ≈ 0.014°. More points shrink it as 1/√N; more length shrinks it directly.

Systematic error comes from lens distortion. A lens specified at 0.3% displacement moves points by 0.003 × 36.2 mm ≈ 0.11 mm — 3.7 px — at the frame's half-width, and over the 60 mm baseline that is 0.11 / 60 ≈ 0.1° of bias, ten times the random budget. Calibrate the lens and the bias falls with the calibration residual, or keep fit points inside the central 60% of the frame where the distortion is a fraction of its edge value. When the acceptance is tighter than 0.1°, start from a lower-distortion optic. The LS-FFL-0567 is a 16 mm C-mount lens printed at <0.3% distortion for 1.1" 20 MP sensors, F2.8-22.

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

Lighting sets the floor under both budgets: glare blobs and soft edges move centroids by whole pixels, which no fitting recovers. The drift sources behind micron-level image measurement accuracy apply here too, only read in degrees.

Common mistakes

  • Fitting coarse-thread crests over one pitch: the projected crest is a wave around the axis. Spread points over many pitches or use the smooth shank.
  • Measuring after rotating the pixels. Resampling adds a few tenths of a pixel of edge uncertainty; measure first, rotate coordinates.
  • A wide-open ROI: background lines carry real weight in least squares. Tight ROI, then trim residuals.
  • Diffuse ring light on polished steel: glare rides the crests. Backlight or raking dark field keeps the silhouette honest.
  • Treating the fixture nominal as the answer: parts roll inside a tolerant nest. Measure the angle per part.
  • Skipping the head-versus-tip check and letting the next station flip the part.

Everything above is one static frame: segment, fit, rotate, refit, accept at 0.1°. To put hardware behind it, start the lens configurator from your sensor and working distance, or filter the camera finder by resolution and interface. More transform and matching mechanics live on the systems topic page, and set-up questions go to contact.

Questions

How many points does the line fit need?

Random angle error shrinks with the square root of the point count: going from 50 to 500 points cuts it by roughly a factor of three. Baseline length helps more: 0.5 px of scatter over a 2,000 px baseline is about 0.014°, while the same scatter over 500 px is 0.057°. Spread points over the full screw and prefer 200 or more.

Does the Radon sweep need a binary image?

No — the transform projects grayscale intensity, so a backlit screw works without a threshold. Thresholding first sharpens the peak and suppresses background texture, which helps on cluttered trays. Keep the sweep range near the fixture nominal: each column costs a full pass over the ROI, so a ±10° sweep is 201 projections while a 0° to 180° scan is 1,801.

Why is the leveled screw still about 0.2° off after refitting?

Usually lens distortion, not the fit. A 0.3% lens bends far-from-center points by roughly 0.11 mm at the example's field, worth about 0.1° of bias over a 60 mm part; uncorrected, plus scatter, that reads as a stubborn 0.1-0.2°. Calibrate the lens, or keep fit points inside the central 60% of the frame where the bias is a fraction of the edge value.

Does rotating the image hurt later measurements?

It can. Each resampling pass interpolates neighbors, and a bilinear rotation adds a few tenths of a pixel of edge uncertainty. Keep measurements on the original frame and rotate the fitted coordinates instead; rotate pixels only for display, archiving or a downstream template match that needs the leveled picture.

Can a smart camera run this loop in production?

Yes. Smart cameras and vision sensors inspect on the device with no PC in the loop, and the arithmetic here is light: a centroid-per-column silhouette, one least-squares fit, one rotation and one refit. Keep the ROI tight — the segmentation over pixels, not the 200-point fit, is what sets the cycle time.