System designTroubleshooting

Full resolution image capture is slow or stalls: size the data first

Full resolution image capture runs slow or stalls after tens of frames: the bandwidth arithmetic, the queue that wedges, and the fixes that work.

LumaSpec Vision10 min read Share on LinkedIn

On this page 9 sections
  1. 01The symptom, and what it rules out
  2. 02First compute the number
  3. 03Worked example: 12 MP color stills over Gigabit Ethernet
  4. 04Cause: the host drains slower than the camera fills
  5. 05Cause: the pixel format ships three times the bytes
  6. 06Cause: the link itself is degraded
  7. 07The decision per case
  8. 08Prevention checklist
  9. 09Questions

A full-resolution grab that runs for a few frames and then goes quiet is almost never a broken camera. It is a sizing problem. A 12 MP color still is about 37 MB, a Gigabit Ethernet link moves roughly 110 MB/s of real payload, and the save loop on the host drains slower than the camera fills. The queue between them backs up, delivery stops, and a downscaled stream keeps running because it needs a quarter of the bytes. This page is for engineers wiring a still-capture or inspection station. You will compute the number for your own resolution and link, isolate the cause that is stalling delivery, and fix it in the queue, the pixel format or the interface.

The symptom, and what it rules out

Full-resolution frames arrive slowly, one every few seconds, and after tens of frames the device stops delivering altogether. The viewer window still runs, the downscaled stream keeps flowing, and closing the application or power-cycling the camera brings full resolution back.

That pattern clears three suspects at once. Exposure and triggering are fine, because frames do arrive. The sensor is fine, because the low-resolution output of the same pipeline still works. The driver did not crash, because the host is still receiving other streams. What remains is the delivery path: the bytes per frame, the rate the link carries them, and the rate your code drains them. The causes below are ordered by how often each explains the stall.

First compute the number

Every fix below follows from two numbers you can calculate before touching the camera:

frame MB = width × height × bytes per pixel ÷ 1,000,000 max fps = link payload MB/s ÷ frame MB

Bytes per pixel depends on the format you actually stream: 1 for 8-bit mono or raw Bayer, 3 for 8-bit RGB straight off the on-camera image processor. Payload is what reaches your application after packet, encoding and protocol overhead, not the line rate. The GigE figure assumes 9000-byte jumbo frames; standard 1500-byte frames take roughly 10-20 MB/s off it.

Link Payload 12 MP raw 8-bit (12 MB) 12 MP RGB8 (37 MB)
GigE, 1 Gbit/s ~110 MB/s ~9 fps ~3 fps
USB3 ~400 MB/s ~33 fps ~11 fps
10GigE ~1100 MB/s ~90 fps ~30 fps
CXP-12, per link ~1250 MB/s ~100 fps ~34 fps

These are link ceilings, so the rate you get is the lower of the ceiling and the sensor's own frame rate. The shop's ratings follow the same arithmetic: the LS-CMR-0053 and LS-CMR-0166 share the IMX226 12 MP sensor, with the GigE model rated 9 fps and the USB3 model 30 fps.

Specification LS-CMR-0053 LS-CMR-0166
Resolution 4000 px x 3000 px 4000 × 3000 (12MP)
Pixel size 1.85 μm x 1.85 μm 1.85 μm
Max. frame rate 9 fps 30 fps
Sensor model IMX 226 Sony IMX226
Shutter Rolling Shutter rolling shutter
Data interface GigE USB 3.0
Pixel bit depth 8 / 10 / 12 bits 10-bit
Price $560.00 $560.00

All 2 share: Sensor size 1/1.7". Values as printed in each product's data sheet; open a part for its drawing and full specifications.

Run that arithmetic for every area scan camera on your shortlist before ordering.

Worked example: 12 MP color stills over Gigabit Ethernet

Inputs, each with its source:

  • Sensor output: 4056 × 3040 pixels, the 12 MP still mode of a color sensor.
  • Pixel format: RGB8, 3 bytes per pixel, color read straight from the on-camera image processor.
  • Link: Gigabit Ethernet, payload about 110 MB/s (a 1 Gbit/s line is 125 MB/s; overhead takes the rest).
  • Host loop: receive, display and write each frame before pulling the next; observed pace one image every few seconds.

The rule in words: the link carries payload ÷ frame size frames per second, the backlog grows at the camera's output rate minus the host's drain rate, and a bounded queue stops delivering once it is full.

4056 × 3040 = 12,330,240 pixels 12,330,240 × 3 bytes = 36,990,720 bytes ≈ 37 MB per frame 37 MB ÷ 110 MB/s = 0.34 s per frame → ceiling ≈ 3 fps drain at 1 frame / 3 s = 0.33 fps backlog ≈ 3 − 0.33 ≈ 2.7 frames per second a 30-frame queue fills in about 11 s

Result: the wire could deliver a full still every 0.34 s, but the observed pace is one every few seconds, so the host loop sets the rate — and a backlog of 2.7 frames per second fills a small queue in seconds. That is the stall after tens of frames.

Decision: for a still session, bound the queue at your still count and receive into memory, writing to disk afterwards; 30 stills × 37 MB ≈ 1.1 GB, which fits any modern host. For live full-resolution color, about 3 fps is the GigE ceiling; USB3 lifts it to about 11 fps and 10GigE to about 30 fps. If the consumer accepts half scale, halving each side cuts the frame to 9.2 MB and the same link carries about 12 fps.

Cause: the host drains slower than the camera fills

Camera and host form a producer and a consumer joined by a queue of fixed size. When the consumer is slower, the queue fills, and then frames drop silently or back-pressure stops the producer. Either way, delivery halts while everything still looks alive.

Two tests split the cases. Print a received-frame counter with timestamps, then comment out the write and display calls: if frames now flow at the payload ceiling, the save path was the constraint. Writing 37 MB to an SSD takes well under a second, but encoding a 12 MP frame to a compressed format costs about a second of CPU on one core, and a display window adds its own delay.

The fixes: bound the queue at the number of frames you need, receive into preallocated buffers and reuse them, move disk writes to a worker thread, and write raw first with compression later. The queue pattern is worked through in Python frame queue memory leak: bound the queue and reuse frames and reuse image buffers instead of per-frame allocation, and image bytes vs pixel data: decode before processing covers what actually arrives in each buffer. For a static scene, trigger single grabs instead of streaming, so the camera produces only what you ask for; single frame acquisition still busy: why repeated starts need a stop shows the start-and-stop pattern.

Where the camera can overshoot the link for a short burst, its onboard buffer absorbs the difference: camera burst capture faster than link bandwidth: use the buffer sizes that case, and acquisition faster than processing: fix the frame rate gap covers the continuous version of the same gap.

Cause: the pixel format ships three times the bytes

RGB8 costs 3 bytes per pixel; raw Bayer 8-bit costs 1. At 12 MP that is a 37 MB frame against a 12 MB one, so the same GigE link carries about 3 fps of color or about 9 fps of raw. If the stall disappears when you switch the stream to the raw format, the format was the constraint; debayer on the host afterwards.

The same lever works in space. Scale on the camera, before the transfer: halving each side removes three quarters of the pixels, a 4× rate gain on any link. Camera-side scaling costs no host CPU and no extra transfers, and it is the right fix whenever the consumer accepts the smaller image.

A GigE port that negotiates down to 100 Mbit/s carries about 11 MB/s of payload, so a 37 MB frame takes about 3.4 s. That turns a few frames per second into one frame every few seconds and mimics a slow host perfectly. Read the negotiated speed on the NIC or switch; if it is not gigabit, swap the cable and give the camera a dedicated port before changing any code. Packet size matters as well: 9000-byte frames cut the packet rate roughly sixfold against 1500-byte frames and strip out per-packet overhead. The failure modes and fixes are in GigE camera packet size error when your link drops below gigabit. Keep capture links wired end to end, because a wireless hop cannot carry this traffic, and give every camera its own port so streams never compete for one NIC.

The decision per case

  • Static scene, tens of stills, GigE: keep the link. Trigger single grabs, bound the queue at your still count, receive into memory, write from a worker thread. Expect about 0.34 s per 12 MP color frame on the wire.
  • Continuous 12 MP mono inspection: GigE carries up to about 9 fps in raw 8-bit. Below that, no change is needed.
  • Continuous 12 MP color: USB3 clears about 11 fps, 10GigE about 30 fps, a CXP-12 link about 34 fps. Order one tier above your target rate so later cameras keep headroom.
  • Any resolution: each extra megapixel adds 1 MB per mono frame or 3 MB per color frame at 8-bit. Rescale the table and re-decide.

Match the tier in the camera finder, then check the arithmetic once more before ordering. When the number lands above your link, the interface is the fix, not the code: a 20 MP mono frame is 20 MB, so the ~400 MB/s USB3 payload carries roughly 20 fps of it.

Area scan camerasHikrobot MV-CS200-10UM 20 MP Area Scan Camera, USB3.0, IMX183, 2nd Gen., MonoMV-CS200-10UM
Sensor format
1"
Lens mount
C-mount
Interface
USB3
Resolution
16-25 MP
$759.00View partBuild a system with it

On the receive side, give each camera a dedicated port; hosts with enough Ethernet interfaces are easy to find among industrial mini PCs, which list LAN port count as a filter. The MV-VC3301H-128G66 is an Intel Core i3 vision controller with 5+ LAN ports and 8 GB of memory. An 8 GB host holds roughly 200 of the 37 MB stills before anything reaches disk.

Vision controllersHikrobot MV-VC3301H-128G66 I3-8100, 8GB+128G SSD, No PoE, PCIe expansion supported, Incl. VM6200Pro licenseMV-VC3301H-128G66
LAN ports
5+ LAN ports
USB 3 ports
3-4 USB 3 ports
Light outputs
4 built-in channels
Memory
8 GB
$2,419.00View partBuild a system with it

Prevention checklist

  • Compute frame MB for the format you will stream, multiply by the rate you need, divide by the payload, and keep about 30 percent headroom for the cameras you will add.
  • Wire each camera to its own NIC port and enable jumbo frames end to end.
  • Stream raw 8-bit unless the task needs host-ready color.
  • Scale on the camera when the consumer accepts a smaller image.
  • Bound the receive queue at the frame count you need, and preallocate and reuse its buffers.
  • Write raw frames from a worker thread; compress afterwards, off the receive loop.
  • Trigger single grabs for static scenes instead of streaming continuously.
  • Release the device cleanly between sessions, so a stale queue does not outlive the viewer window.

Size your own station with the configurator, or ask the applications team with your resolution, pixel format and target rate. The rest of the stream and timing failures live on the systems topic page.

Questions

How many bytes does one frame from my camera produce?

Multiply width × height × bytes per pixel. At 8 bits: 5 MP mono ≈ 5 MB, 12 MP mono ≈ 12 MB, 20 MP mono ≈ 20 MB, 25 MP RGB ≈ 75 MB. Color read straight off an image processor is 3 bytes per pixel, so a nominal 12 MP color frame is about 36 MB, and the exact 4056 × 3040 read is 37 MB. 10- and 12-bit formats unpack to 2 bytes per pixel, doubling every figure.

Why do downscaled frames keep flowing while full resolution stalls?

Halving each side removes three quarters of the pixels, so the link that carries about 3 full 12 MP color frames per second carries about 12 half-scale ones. The queue then drains as fast as the camera fills it, so nothing backs up and nothing wedges. Restore full resolution without raising the drain rate, and the same stall returns.

How fast should a Gigabit Ethernet camera link actually transfer?

A 1 Gbit/s line is 125 MB/s, and after overhead about 110 MB/s reaches your application as payload with jumbo frames. Measure received bytes over a timed bulk transfer rather than trusting rated fps. If the measurement sits near 11 MB/s, the link has negotiated down to 100 Mbit/s; if it sits under about 90 MB/s, look at packet size, cable quality and shared switch ports.

How much host memory do I need to grab stills first and write later?

Queue depth times frame size. Thirty 12 MP color stills at 37 MB need about 1.1 GB; a hundred need about 3.7 GB, which fits an 8 GB host alongside a modest application. Keep the queue bounded at the number of stills you actually want, because an unbounded queue turns the same stall into a memory leak instead.

Does saving frames as PNG or JPEG slow the capture down?

Not the network, but your loop. Encoding a 12 MP frame typically costs about a second of CPU on one core, slower than the 0.34 s a GigE link needs to move it, and a display window adds its own delay. Write raw or uncompressed frames in the receive loop and encode in a worker thread afterwards, and compression stops setting the pace.