System designExplainer

Why pixel shifts change detection results and how to stabilize them

Every resize, crop or pixel shift changes the input tensor a detector sees. Freeze the ROI, letterbox size and interpolation to stabilize results.

LumaSpec Vision12 min read Share on LinkedIn

On this page 9 sections
  1. 01Why a few pixels move the whole output
  2. 02The letterbox arithmetic
  3. 03Worked example: a 30×22 px label on a 1280×960 frame at 640×640
  4. 04Where the variation enters your line
  5. 05Freezing the geometry: the fix in five steps
  6. 06When the usual fixes do not help
  7. 07Hardware that holds the geometry
  8. 08Checks before you deploy
  9. 09Questions

You train a detector, it passes on the bench, and on the line the boxes flicker: found, then missed, then found at a lower score, with no visible change at the station. The part did not move. The frames did. A convolutional detector reads the image as a tensor of numbers, and a resize or crop that differs by a handful of pixels changes nearly every one of those numbers before the first layer runs. This page shows where that pixel-level variation enters a machine-vision pipeline, works the letterbox arithmetic through a realistic frame, and gives the fix on the acquisition side: a fixed ROI on the camera, one letterbox size, one interpolation and a hardware trigger. It applies to neural detectors on smart cameras and on PC-based area scan systems alike.

Why a few pixels move the whole output

Before the first convolution, the preprocessing resizes the captured frame to the network input. Most modern one-stage detectors use a square letterbox canvas, 640×640 px being the common size: the long side of the frame is scaled to fit, the short side is padded to fill. Every later stage - the convolution stacks, the stride-8, 16 and 32 grids that assign objects to cells, the box regression - reads only that canvas.

Resizing is interpolation. Bilinear resampling writes each output pixel as a weighted mix of its 2×2 nearest input neighbors, so when the canvas geometry changes by even 5 px, the scale changes and every content pixel mixes a different neighborhood. The padding split moves with it. The result is not a slightly shifted image but a new tensor in which almost no element kept its exact value.

Sensitivity is worst for small features. The widely used COCO small-object convention treats anything under 32×32 px at the network input as small, because little visual information survives the downsampling. Published measurements point the same way: a shift of about 6 px barely moves a large bounding box, while it can collapse the overlap score of a small one. A feature sitting at 15×11 px has no margin left to spend.

Even sub-pixel motion matters. An edge straddles several sensor pixels, so image motion smaller than one pixel still changes the mix ratios and the pixel values, without the part visibly going anywhere.

The companion page on object detector input dimensions: height, width, and padding walks through how frameworks arrive at height, width and padding in the first place.

The letterbox arithmetic

Four relations govern the whole effect. For a captured frame of W×H px, a network input side of N px (640 in this example) and a feature measuring w×h px on the sensor:

s = N / max(W, H) w_in = w × s h_in = h × s pad = (N - min(W, H) × s) / 2

The scale s is dimensionless; the other results are in pixels. Two failure modes fall straight out of the relations. First, s moves whenever W or H moves by so much as a pixel, and the padding moves with it. Second, w_in shrinks in proportion, so a feature that clears 32×32 px at one scale drops under the line at a slightly smaller one. Holding W, H and N fixed in hardware and configuration removes both modes at once.

Worked example: a 30×22 px label on a 1280×960 frame at 640×640

The case: a laser-etched code area on a part, inspected by a smart camera that lettersboxes to 640×640 px. The frame and feature sizes below are an illustrative working point; any W×H behaves the same way.

The inputs:

  • Captured frame: 1280×960 px, delivered by a fixed camera ROI.
  • Inspected feature: 30×22 px on the sensor.
  • Network input: 640×640 px, letterboxed, bilinear interpolation.
  • Perturbations under test: shave 5 px off the left edge of the frame; extend the canvas 3 px on the right - the pixel-level edits that reproduce the instability.

Baseline. s = 640 / 1280 = 0.500. Content: 1280 × 0.500 = 640 px wide, 960 × 0.500 = 480 px tall, so pad = (640 - 480) / 2 = 80 px top and bottom. Feature at the input: 30 × 0.500 = 15 px and 22 × 0.500 = 11 px - already under the 32×32 px small-object line.

Shave 5 px, so W = 1275 px. s = 640 / 1275 = 0.502. Content height: 960 × 0.502 = 482 px, so pad = (640 - 482) / 2 = 79 px. Feature: 30 × 0.502 = 15.1 px and 22 × 0.502 = 11.0 px, rasterized again as 15×11 px.

Extend 3 px, so W = 1283 px. s = 640 / 1283 = 0.499. Content height: 960 × 0.499 = 479 px, so pad = (640 - 479) / 2 = 80 px per edge after rounding. Feature: about 15×11 px again.

Result. Three frames that look identical deliver three different tensors: scale 0.500, 0.502 and 0.499; padding 80, 79 and 80 px; and every content pixel a different bilinear mix. The label lands at a different offset inside the stride-8 grid - at 15×11 px it spans roughly two cells across, and where its center falls decides which cells count as positives. For a feature at a third of the small-object line, those deltas are enough to push confidence across the score threshold, which is exactly what production flicker looks like.

Decision. Give the feature margin and take the variation away. At this scale the code area should measure at least 64×64 px on the sensor - exactly 32×32 px at the input - and more where the optics allow, because at the line itself there is no margin left. Hold W×H fixed so s never leaves 0.500. If the optics cannot deliver the pixels, narrow the ROI or shorten the focal length; do not try to fix it in the model.

Where the variation enters your line

Six stages cause almost all of it. Each row is testable in isolation: capture twenty frames while varying only that stage and count the box flips.

Pipeline stage What varies Effect at the network input Fix
Crop / ROI Frame W×H drifts by pixels between frames New scale s and new padding every frame Set the ROI on the camera and leave it
Resize A different resize library or filter than training Different values in every content pixel One interpolation, the same one training used
Padding Value or placement differs from training Border cell statistics shift Same padding value and placement as training
Trigger Part sits at a different position each cycle Feature lands on different stride cells Hardware trigger at a fixed position
Shutter Rolling shutter shears a moving part Smear changes with belt speed Global shutter
Exposure / gain Auto exposure tracks the scene Pixel values drift, scores wander Manual exposure with fixed lighting

The ROI and resize rows do the most damage on PC-based stacks because they change the scale itself. The trigger and shutter rows dominate on fast moving lines. Exposure deserves attention even on a fixed bench, because auto exposure re-scales pixel values and lets scores wander with ambient light; the guide on ambient light variation in pick and place vision covers the lighting side.

Freezing the geometry: the fix in five steps

  1. Set the ROI on the camera. Configure width, height and offset as camera settings so every delivered frame has the same W×H; do not crop in application code after capture. When a region genuinely has to be located in software, the guide on cropping an image ROI when the corner coordinates are unknown shows how to find it reproducibly.
  2. Letterbox to the trained size, every frame. Resize and pad to 640×640 px, or whatever the model was trained on, with the same padding value and placement - including no-part frames, so an empty canvas still looks like the canvases the model saw.
  3. Standardize the resize. One implementation, one named interpolation filter, at training and at deployment; published preprocessing work lists letterbox and padding placement together with interpolation changes among the likely causes of differing outputs between environments. On a smart camera, run the resize inside the camera pipeline and keep the host out of the pixel path.
  4. Trigger in time as well as in space. Hardware-trigger each cycle at a fixed part position so the feature lands on the same stride cells. On a moving line, use a global shutter so the part is not sheared mid-exposure, and keep the exposure short: at 1 m/s belt speed, a 20 µs exposure smears the image 0.02 mm.
  5. Freeze exposure and gain. Manual values with fixed lighting. Auto exposure tracks the scene and moves scores even with perfect geometry, and feedback from the detector itself can make it hunt, as the write-up on auto exposure ROI instability from detection feedback shows.

Verification. Stage one part, capture 50 frames and run inference on all of them: zero class flips, and box centers steady to within a pixel or two. Then move the part ±2 mm across the field: the boxes must track smoothly instead of appearing and disappearing. Byte-identical frames that still produce different outputs point at the runtime, not the camera - pin the batch size to 1 before you conclude anything.

When the usual fixes do not help

  • More training augmentation hardens the model against variation but does not remove it. Near the score threshold, a deterministic input still decides pass and fail. Fix the geometry first, then judge the model.
  • A lower confidence threshold buys recall and pays in false rejects. The input tensor still changes every frame; you have moved the noise, not removed it.
  • A bigger model cannot recover pixels that were never sampled. At 15×11 px after letterbox, no backbone finds structure the resize averaged away - raise the pixel budget at the sensor instead. That is the same logic as the pixel rule that sizes camera resolution for defect detection, and it applies unchanged here.
  • Classical tools sit on the same inputs. Fixed geometry and fixed light stabilize template matching too, which is the discipline behind the guide on edge-based pattern matching for stable results when lighting changes.

Hardware that holds the geometry

Two deployment shapes hold a fixed geometry naturally. On-device, a smart camera captures, resizes and infers in one runtime, so the ROI and the letterbox are set once and cannot drift apart between two programs; the smart cameras range spans vision sensors with fixed M12 lenses up to x86-platform C-mount units.

Within that range: the LS-SMC-0063 ships with its 16 mm lens and white light and runs 60 fps for small fields. The MV-SC5060XM-08M-WBN steps up to a 6 MP sensor with an 8 mm M12 lens over GigE. The MV-SC6050C-08M-XBN pairs 5 MP with a global shutter and a built-in multi-color light source.

Smart cameras & vision sensors1.6 MP smart camera, 60 fps, 16 mm lens, white light (polarized, transparent light) (LS-SMC-0063)LS-SMC-0063
Interface
GigE
Resolution
Up to 3 MP
$1,110.00View part
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
$1,629.00View part
Smart cameras & vision sensorsHikrobot MV-SC6050C-08M-XBN SC6000 Series Smart Camera, 5 MP, Color, 8 mm focal length, M12-mount, Multi-color light sourceMV-SC6050C-08M-XBN
Interface
GigE
Resolution
5 MP
$3,449.00 · quotedView and quote

PC-based stacks hold the same discipline at the capture library: set ROI and pixel format on the area scan cameras side and leave them alone. When the feature needs more sensor pixels, step the camera up. At a 0.5 letterbox scale, 32×32 px at the network input means 64×64 px on the sensor. A 12 MP global-shutter USB3 camera such as the MV-CH120-11UC provides that headroom.

Area scan camerasHikrobot MV-CH120-11UC 12 MP Area Scan Camera, USB3, IMX304, High-speed version, ColorMV-CH120-11UC
Sensor format
1.1"
Lens mount
C-mount
Interface
USB3
Resolution
12 MP
$2,339.00 · quotedView and quoteBuild a system with it

Size the pixel budget before you freeze anything. The rule is the one that sizes inspection resolution everywhere - enough pixels on the smallest feature - and the calculator below works it from your field of view and smallest feature, then opens the camera finder filtered to cameras with enough pixels.

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

Checks before you deploy

  • One frame size on the wire. Log the delivered W×H for a minute of production; every frame must match. A post-crop sneaking back into the code shows up here first.
  • One canvas. Assert the 640×640 px input and the padding value inside the preprocessing code, where a change fails loudly.
  • One filter. Name the interpolation in code and search the project for a second resize path; debug overlays and thumbnail generation are the usual offenders.
  • Repeatable trigger. With the line stopped, boxes at rest must not flicker; cycling the same part twenty times must give twenty stable results.
  • Feature margin. Measure the smallest feature in the delivered frames. It should clear 32×32 px at the network input with margin - 40×40 px is a sound target.

Freeze W×H, freeze the canvas, freeze the filter - then re-run the bench pass on the line. If results still wander with byte-identical frames, the residue is in the runtime, not the optics. To choose the camera side, start at the camera finder, work through configure a camera, or browse the vision systems learn articles; if the part is awkward, the contact page puts you straight through to the applications team.

Questions

How many pixels does a part need for stable detection?

Work from the network input, not the sensor. Keep every inspected feature at 32×32 px or larger after letterbox - the widely used small-object line. Divide by the letterbox scale for the sensor size: at a scale of 0.5 that means 64×64 px on the sensor, at 0.25 it means 128×128 px. If the optics cannot deliver that, narrow the ROI or shorten the focal length before touching the model.

Does the GPU or batch size cause the flicker too?

Pixel-level input changes dominate, but run-time libraries can add their own variance: some runtimes pick convolution algorithms while running, so the same tensor can differ slightly between batch sizes or after a restart. For stability checks, fix the batch size at 1 and compare byte-identical tensors; if boxes still move with identical inputs, the cause is in the runtime, not the camera.

What should the letterbox padding look like?

Whatever training used - same value and same placement, normally neutral gray bars centered along the short side. Padding is not cosmetic: the bars sit inside the receptive field of border cells, so a different padding value, or a top-left placement where training centered the content, shifts border statistics enough to move detections near the frame edge.

Can a moving conveyor be stabilized too?

Yes - freeze the geometry in time as well as in pixels. Trigger the camera from a photoelectric sensor or encoder at a fixed part position, use a global shutter so the part is not sheared mid-exposure, and keep exposure short: at a 1 m/s belt speed, a 20 µs exposure limits smear to 0.02 mm, a fraction of a pixel on most line setups.

Is this related to pixel-shift cameras that increase resolution?

Only the name. Sensor pixel-shift imaging steps the imager by half a pixel between exposures and combines the frames into one higher-resolution image. It changes what the sensor records, not how the detector resamples it. The instability described here comes from resize, crop, padding and interpolation differences before inference, which fixed-ROI capture and a fixed letterbox remove.