You can compute a machine-vision camera's frame time before acquisition starts, and a scan plan should be built on that number, not on a trial run. Three limits set the period between frames: your exposure time, the sensor's readout time at the current Height, and the wire time for one frame's bytes. The slowest limit wins, and each limit is predictable from settings you already chose. What follows is the rule, a 12 MP camera worked through three settings with the arithmetic written out, and the two checks that close the loop: the camera's calculated-frame-rate node before you start, and the timestamp chunk once frames are flowing. It applies to any area scan camera on GigE, USB3, 10GigE or CoaXPress.
The rule: the slowest of three limits wins
In continuous acquisition with overlap enabled, the normal free-running mode, the frame period is the largest of three times:
T_exposure is your ExposureTime setting. T_readout is the time the sensor needs to shift one frame off the array, and it scales with the rows you scan: Height sets it, OffsetY does not. T_link is the wire time for one frame at the interface's usable throughput R_link. Count 1 byte per pixel for any raw format: Mono8 and Bayer both put 1 byte per pixel on the wire, and colour comes from debayering in the host. Packed RGB counts 3.
Usable throughput, with its basis: GigE runs near 118 MB/s with jumbo packets, the 1 Gb/s line rate minus Ethernet, IP and UDP overhead, and slower stacks land between 105 and 118 MB/s. USB 3.0 delivers about 360-400 MB/s in practice. A 10GigE link carries roughly 1,100 MB/s. Changing the pixel format changes the bytes, not the ceiling; the BGR versus Bayer frame-rate drop shows the effect on GigE in numbers.
Triggered acquisition changes one term. If the camera waits for the exposure to finish before reading out, with no overlap or with exposure tied to the trigger pulse, the period is T_exposure + T_readout, the arithmetic behind the hardware-trigger frame-rate guide. In continuous mode an exposure longer than the readout stretches every period by exactly the extra milliseconds, which is the drop behind why GigE frame rates fall at longer exposures.
What you need before the calculation
- The printed maximum fps and full resolution from the camera's data sheet. This anchors the readout estimate.
- Your planned ExposureTime, Width, Height, PixelFormat and binning.
- The link you will run and its bytes per pixel.
- The timing nodes for confirmation: SensorReadoutTime and ResultingFrameRate, standard GenICam features that most SDKs expose as read-only values.
- Timestamp chunk support, for the delivered-rate check after start-up.
If the host side is not settled yet, a two-port PoE GigE adapter is the standard base for a GigE camera. The camera decides the arithmetic; the adapter decides whether the wire can keep it.
Estimate the readout time in five steps
- Anchor the full-frame readout: divide one second by the printed maximum fps. A camera printing 30 fps reads out in 1 / 30 s = 33.3 ms.
- Get the row time: divide by the sensor's full Height in rows. 33.3 ms / 3000 rows = 11.1 µs per row.
- Scale to the ROI: multiply the row time by your Height. A 1000-row window reads out in 11.1 µs × 1000 = 11.1 ms. Binning changes the row count, as the binning versus readout guide shows.
- Compare with ExposureTime: the larger one sets the sensor-side period in continuous mode.
- Cap by the wire: divide frame bytes by the link throughput, then take the largest of the three periods.
Treat the scaled readout as an estimate: a few sensors add a fixed vertical overhead the scaling misses, and SensorReadoutTime, computed by the camera from its own clocking, prints the exact figure at your ROI. The correction is usually a few percent, not a different regime.
Worked example: a 12 MP camera at three settings
The inputs
The camera is a 12 MP rolling-shutter sensor with a 4000 × 3000 array. The LS-CMR-0166 prints 30 fps at its full 4000 × 3000 resolution over USB3. The LS-CMR-0053 prints 9 fps over GigE on the same IMX226 sensor.
Both parts print the IMX226 sensor; the wire is the only difference.
- Sensor format
- 1/1.7"
- Lens mount
- C-mount
- Sensor format
- 1/1.7"
- Interface
- USB3
Your scan: a 10 ms exposure, continuous acquisition with overlap on, raw output at 1 byte per pixel. The wire ceilings from the rule above apply: about 118 MB/s on GigE and 360 MB/s on USB3.
Setting 1: full frame, 10 ms exposure
Readout: 1 / 30 fps = 33.3 ms, so the row time is 33.3 ms / 3000 rows = 11.1 µs. Frame size: 4000 × 3000 pixels × 1 B = 12.0 MB. USB3 wire time: 12.0 MB / 360 MB/s = 33.3 ms, the same as the readout, because 12.0 MB × 30 fps is exactly a 360 MB/s stream; this camera runs its link at the ceiling. GigE wire time: 12.0 MB / 118 MB/s = 101.7 ms.
Period = max(10 ms exposure, 33.3 ms readout, 101.7 or 33.3 ms wire). On GigE that is 101.7 ms, or 9.8 fps; on USB3 it is 33.3 ms, or 30 fps. The 10 ms exposure costs nothing at full frame. The GigE figure lands next to the printed 9 fps: 12.0 MB × 9 fps = 108 MB/s, just under the ceiling, which is the behaviour of a wire-limited camera.
Setting 2: a 4000 × 1000 ROI, 10 ms exposure
Readout: 11.1 µs × 1000 rows = 11.1 ms, or 90 fps sensor-side. Frame size: 4000 × 1000 × 1 B = 4.0 MB. USB3 wire: 4.0 MB / 360 MB/s = 11.1 ms, so the link ties the sensor and about 90 fps is the deliverable ceiling with no headroom. GigE wire: 4.0 MB / 118 MB/s = 33.9 ms, or 29.5 fps; the wire is now the period, not the sensor.
The 10 ms exposure still costs nothing. Decision so far: the same sensor and window deliver 90 fps on USB3 and 29 fps on GigE, and the difference is entirely bytes on the wire.
Setting 3: a 4000 × 1000 ROI, 60 ms exposure
Exposure 60 ms now exceeds readout 11.1 ms and USB3 wire 11.1 ms. Continuous mode: period = 60 ms, or 16.7 fps. Triggered without overlap: period = 60 ms + 11.1 ms = 71.1 ms, or 14.1 fps. The exposure is the ceiling in both regimes, and each extra millisecond of exposure adds exactly one millisecond to the period.
| Setting | Sensor period | GigE wire | USB3 wire | GigE result | USB3 result |
|---|---|---|---|---|---|
| 4000 × 3000, 10 ms | 33.3 ms | 101.7 ms | 33.3 ms | 9.8 fps (9 printed) | 30 fps |
| 4000 × 1000, 10 ms | 11.1 ms | 33.9 ms | 11.1 ms | 29.5 fps | 90 fps |
| 4000 × 1000, 60 ms | 60 ms, 71.1 ms triggered | 33.9 ms | 11.1 ms | 16.7 / 14.1 fps | 16.7 / 14.1 fps |
The decision
For this scan, a 1000-row window with a raw stream and a 10 ms exposure, a GigE link buys about 29 fps and a USB3 link about 90 fps. Above 11.1 ms, exposure sets the period at 1 ms per ms. To pass 90 fps at this window: fewer rows (800 rows read out in 11.1 µs × 800 = 8.9 ms, a 112 fps ceiling), on-chip binning, or a faster link. At full resolution the sensor itself is the ceiling at 30 fps, and only a different sensor changes that.
Confirm the number with the camera's own nodes
Before acquisition, read ResultingFrameRate. The camera computes it from ExposureTime, Width, Height, PixelFormat and its own throughput settings; on GigE that includes packet size, packet pacing and throughput limits, so a throttled link shows up in the node and not just in your wire math. If your hand calculation and the node differ by more than a few percent, a link throughput setting is the reason.
Once frames flow, enable the timestamp chunk and subtract consecutive ChunkTimestamp values. That difference is the frame period in camera-clock time, untouched by host load or processing spikes. A histogram of the deltas is the delivered period; spread in the histogram means dropped frames or a starved trigger, not a slow sensor. The chunk timestamp guide covers latching the value at exposure end, and chunk data carried per image shows how the values travel on the frame.
Five mistakes that skew the result
- Trusting the host counter. Software-reported fps often mixes acquisition with processing, and some libraries return zero or the configured rate instead of the delivered one. Read the timestamp chunk, or see when video fps returns zero in OpenCV.
- Changing pixel format without recalculating. Packed RGB triples the bytes per pixel and divides a wire-limited rate by three; formats can also drag linked attributes with them, as in why changing pixel format halves the frame rate.
- Assuming offsets speed up readout. OffsetX and OffsetY place the window; only Height and binning change the rows the sensor scans.
- Forgetting the trigger regime. With pulse-width exposure or no overlap, the period is exposure plus readout, not the maximum, as trigger pulse width and exposure explains. A slow trigger source adds its own gap, as in why a USB camera misses 2 fps through an Arduino.
- Host-side caps. A Linux usbfs memory limit or a saturated host link throttles delivery below the calculated rate; the USB3 low-frame-rate fix is the usual cure, and the gap between calculated and delivered rate is the number to watch in when acquisition outruns processing.
When the wire is the ceiling
When the wire period exceeds the sensor period, 33.9 ms against 11.1 ms in Setting 2, no ROI setting recovers the rate, because the bytes have nowhere to go. Move the bottleneck: a 10GigE link carries about 1,100 MB/s, so the 4.0 MB frame costs 4.0 / 1100 = 3.6 ms of wire time, far below the 11.1 ms readout. The host needs a 10GbE port; the quad-port copper 10GbE NIC provides four, one camera per port, and beyond a handful of cameras frame grabbers with on-board buffering absorb delivery jitter. Past a few hundred fps the selection logic changes: sensor class, shutter type, on-camera data reduction. The 5,000 fps selection guide walks that decision end to end.
The MV-CH120-11UC is the USB3 side of that choice: a 12 MP global-shutter camera for scans limited by the sensor. The MV-CH250-25TC-F-NF pairs a 25 MP PYTHON25K sensor with a 10GigE interface and an F-mount for scans limited by the wire.
- Sensor format
- 1.1"
- Lens mount
- C-mount
- Sensor format
- APS-H
- Lens mount
- F-mount
The three-line recap
Run the three-line calculation, read ResultingFrameRate, then histogram the timestamp deltas, in that order, because each step catches a different limit: sensor, link, delivery. If the period misses the scan budget, fix in this order: shorten Height, enable binning, cut bytes per pixel, then move the interface. The camera finder filters by interface and high-speed type when the sensor is the ceiling, the configurator starts at the camera step, and the contact page is where to send an ROI, pixel format and target fps for us to run the same arithmetic on your numbers. More timing guides sit on the cameras topic page.
Questions
Does moving the ROI down the sensor make the camera faster?
No. On a sensor that addresses rows directly, readout time scales with the rows scanned, so Height sets it; OffsetX and OffsetY only place the window inside the full scan. A 1000-row window reads out in the same 11.1 ms anywhere on a 3000-row sensor. Some sensors add a fixed vertical overhead that no ROI removes, which is why the camera's own readout-time value beats any hand calculation.
Why does RGB pixel format cut the frame rate on GigE?
Bytes per pixel triple: a 4000 × 1000 Mono8 frame is 4.0 MB, the same window in RGB8 is 12.0 MB, and the GigE ceiling stays near 118 MB/s, so a wire-limited 29 fps drops below 10. Keep the camera sending raw (Mono8 or Bayer, 1 byte per pixel on the wire) and do the colour conversion in the host, where the CPU is cheaper than the link.
How do I catch the frame interval my camera actually delivers?
Enable the timestamp chunk so every image carries the camera's clock reading at exposure end, then subtract consecutive ChunkTimestamp values and histogram the differences. That measures camera time, untouched by host load. Software counters mix acquisition with processing, and some libraries report zero or the configured rate instead of what arrived; the timestamp delta never does. Irregular deltas mean dropped frames or a starved trigger, not a slow sensor.
Does binning raise the frame rate?
Usually, on two fronts at once. Vertical binning merges rows on chip, so the sensor scans fewer effective rows: 2 × 2 binning on the 3000-row example turns an 11.1 µs row time into a 16.7 ms frame, 60 fps instead of 30. The frame also shrinks in bytes, which lifts a bandwidth-limited GigE camera the same way. Check the sensor's binning modes first; some formats bin only horizontally.
What is the quickest way to predict fps before ordering a camera?
Three lines: divide one second by the printed full-frame fps for the readout period; scale it by your Height fraction; then divide frame bytes by the interface throughput and keep the largest of the three times. Use about 118 MB/s for GigE, 360-400 MB/s for USB3 and 1,100 MB/s for 10GigE, all at 1 byte per pixel for raw formats. The camera's ResultingFrameRate node confirms the arithmetic once you can connect one.



