System designHow-to

Set camera ROI in Python: size, offsets and persistence

Set camera ROI in Python with valid width, height and offsets, verify the acquired pixels, and choose startup settings or saved user sets.

LumaSpec Vision10 min read Share on LinkedIn

On this page 10 sections
  1. 01Choose sensor cropping rather than resizing
  2. 02Establish the feature interface before writing settings
  3. 03Calculate the requested size and position
  4. 04Apply the ROI before starting acquisition
  5. 05Verify the acquired image, not only the feature values
  6. 06Choose application startup or persistent user sets
    1. Application-controlled startup
    2. Camera-controlled persistence
  7. 07Diagnose rejected writes and unexpected crops
  8. 08Check camera and host compatibility before ordering
  9. 09Preflight checklist and next step
  10. 10Questions

Changing the size of a displayed image is not the same as changing the pixels acquired by a camera. If you need a smaller sensor region, configure the acquisition features before streaming and verify the returned image, not just the preview window. This procedure explains how to select image dimensions and offsets in Python, reject unsupported settings, and decide whether configuration belongs in your application or a camera user set.

Choose sensor cropping rather than resizing

An acquisition region of interest, or ROI, selects a rectangular portion of the sensor image. Width and Height commonly describe its dimensions; OffsetX and OffsetY commonly describe its position. Feature availability and coordinate conventions remain camera-dependent.

Reducing dimensions without changing the offsets normally keeps the ROI at its existing origin. If that origin is the upper-left corner, the image shows that corner rather than a smaller version of the whole scene. Nothing has necessarily failed: cropping removes image content outside the selected rectangle.

Operation What changes Does it preserve the entire original scene?
Acquisition ROI Selected image area and transmitted dimensions No
Host resizing Dimensions after acquisition Yes, if the entire image is resized
Binning Sampling through supported pixel aggregation Depends on the selected image area
Subsampling Sampling through supported pixel skipping Depends on the selected image area
Transport compression Encoded representation of image data It does not reposition the ROI

Use the acquisition cropping and bandwidth explanation when deciding where to reduce data. The ROI, binning and subsampling comparison explains their different sampling effects.

If your requirement concerns only an operator preview, follow the display window size and position procedure instead. Changing camera ROI to fit a window discards inspection content unnecessarily.

Establish the feature interface before writing settings

You need the manufacturer's supported Python SDK, a device opened with configuration access, and access to its remote-device feature map. Install software and obtain documentation through the manufacturer or an authorized distributor.

A Python SDK might expose features as attributes, typed nodes, or name-based accessors. Consequently, an expression such as camera.Width = value is not portable across SDKs. Attribute assignment can also be the wrong operation for a binding that expects a node setter.

Before configuration, establish these facts:

  • Which SDK operation opens the selected camera with write access?
  • Which feature map contains the camera's acquisition features rather than host transport settings?
  • How does the binding report feature availability, readability and writability?
  • How are integer minimum, maximum and increment values obtained?
  • How does the application stop acquisition and release outstanding image buffers?

Do not assume a feature exists because a similarly named control appears in another camera's software. If a selector controls the active region, select the intended region first. Disable automatic centering only when the camera documents that mode and provides a supported way to change it.

This procedure assumes a single rectangular ROI with independently writable offsets and regular integer increments. Fixed, automatically centered or multiple-region modes need their documented configuration sequence.

Calculate the requested size and position

Suppose an example camera currently captures a full image measuring 1280 × 1024 pixels. Your application needs an 800 × 600 pixel crop centered within that image. Assume zero-based offsets and no binning, subsampling or image reversal.

OffsetX = (full image width - ROI width) / 2 OffsetY = (full image height - ROI height) / 2 OffsetX = (1280 - 800) / 2 = 240 pixels OffsetY = (1024 - 600) / 2 = 212 pixels

These calculations provide requested coordinates, not proof that the camera accepts them. Read the feature limits to establish validity.

For a feature with minimum minimum and increment increment, a candidate must satisfy both conditions:

minimum <= candidate <= maximum (candidate - minimum) modulo increment = 0

For example, a zero-based offset with a 4-pixel increment accepts 212 pixels. With an 8-pixel increment, the nearest candidates are 208 and 216 pixels. Each shifts the crop center by 4 pixels from the requested position.

Choose and record an alignment policy rather than silently rounding. A measurement application may need to reject the request; a localization task may accept a documented shift.

For a conventional, untransformed image, the rectangle must also fit inside the available image area:

OffsetX + Width <= available image width OffsetY + Height <= available image height

Use the camera's documented coordinate system when binning, reversal or other acquisition modes are enabled. The image returned by a previous crop is not necessarily the full available image area.

Apply the ROI before starting acquisition

  1. Open the intended device and stop acquisition. Select the device by a stable identifier rather than assuming enumeration order. Stop the application acquisition loop, stop the stream through the supported SDK, and release outstanding buffers as documented.

  2. Set acquisition modes that affect geometry first. Pixel format, binning, subsampling and region selection can change allowed dimensions or increments. Read ROI constraints after these settings, not before them.

  3. Move writable offsets to their supported minimum, then set dimensions and final offsets. This is a common sequence for independently positioned ROIs. It prevents an old offset from blocking a larger requested width or height. Follow a different sequence when the camera documentation requires one.

The following Python code uses an application-defined adapter named features. Its methods are not universal SDK calls. Bind them to the manufacturer's documented feature-access functions. integer_limits() must return the current minimum, maximum and positive increment, and must reject unsupported constraint formats.

def write_integer(features, name, value):
    if not features.readable(name):
        raise RuntimeError(f"{name} is unavailable or unreadable")
    if not features.writable(name):
        raise RuntimeError(f"{name} is not writable")

    minimum, maximum, increment = features.integer_limits(name)
    if increment <= 0:
        raise RuntimeError(f"{name} has no usable regular increment")

    if not minimum <= value <= maximum:
        raise ValueError(
            f"{name}={value} is outside {minimum}..{maximum}"
        )
    if (value - minimum) % increment:
        raise ValueError(
            f"{name}={value} does not match increment {increment} "
            f"from minimum {minimum}"
        )

    features.write_int(name, value)
    actual = features.read_int(name)
    if actual != value:
        raise RuntimeError(f"{name}: requested {value}, read {actual}")


def apply_roi(features, width, height, x, y):
    # Call only with acquisition stopped and buffers released.
    for name in ("OffsetX", "OffsetY"):
        minimum, _, _ = features.integer_limits(name)
        write_integer(features, name, minimum)

    write_integer(features, "Width", width)
    write_integer(features, "Height", height)
    write_integer(features, "OffsetX", x)
    write_integer(features, "OffsetY", y)

    expected = {
        "Width": width,
        "Height": height,
        "OffsetX": x,
        "OffsetY": y,
    }
    actual = {
        name: features.read_int(name)
        for name in expected
    }
    if actual != expected:
        raise RuntimeError(f"Final ROI differs: {actual}")
    return actual

Each write queries fresh limits because an earlier write may change a later feature's maximum. The final readback also catches interactions that alter previously written features.

  1. Restart only after configuration succeeds. Refresh or reallocate acquisition buffers when required by the SDK. If configuration raises an exception, keep acquisition stopped and report the partially applied state. The example does not provide transactional rollback.

Where offsets are absent or fixed, omit those writes only after confirming the camera's documented positioning behavior. Do not suppress all feature-access exceptions and continue with an unknown image geometry.

Verify the acquired image, not only the feature values

Acquire a test image after successful configuration. Confirm that its reported width and height match the requested dimensions, and that the decoded array has the expected shape.

For a grayscale array, an 800 × 600 pixel ROI commonly produces a shape of (600, 800): rows precede columns. A converted color image may add a channel dimension. Packed formats, padding and metadata require interpretation through the SDK rather than assumptions about buffer length.

The example crop contains 800 × 600 = 480,000 pixels, compared with 1280 × 1024 = 1,310,720 pixels originally. That is approximately 36.6% of the original pixel count. For unpacked monochrome data at one byte per pixel, the image samples occupy 480,000 bytes before padding or metadata.

A smaller pixel count does not guarantee a proportional frame-rate increase. Sensor readout, exposure and transport can remain limiting factors.

Place a recognizable target near the intended ROI boundary and confirm its position. If interpreting the returned buffer is uncertain, use the image bytes versus decoded pixel data explanation.

Choose application startup or persistent user sets

Writing ROI features usually changes the active camera state. Whether that state survives closing the application or removing power depends on documented camera behavior. A successful write alone is not evidence of persistence.

Application-controlled startup

For software-controlled equipment, a repeatable startup configuration is often the clearest choice:

  • Open the intended device.
  • Load any documented baseline configuration before applying overrides.
  • Set acquisition modes and ROI in a defined order.
  • Read back and log the final settings.
  • Allocate buffers and begin acquisition.

Store the requested geometry in your application configuration. Avoid relying on settings left behind by a separate configuration utility.

The manual exposure startup sequence illustrates the same ordering issue: a later configuration load can overwrite an earlier feature write.

Camera-controlled persistence

Some cameras provide persistent user sets. Common GenICam feature names include UserSetSelector and UserSetSave; some implementations use UserSetDefault to select a startup set. Names, supported selections and saved feature coverage vary.

Use the manufacturer's documented sequence to select a writable set and save the intended configuration. If automatic loading at power-up is required, configure that separately where supported. Selecting a set does not necessarily load it, and saving it does not necessarily make it the startup set.

Test application restart, device reopening and an authorized power cycle as separate cases. Read back all ROI features afterward. Save deliberate configuration changes, not every frame or every routine startup.

Diagnose rejected writes and unexpected crops

Symptom Likely cause Targeted test and correction
Width or height is not writable Acquisition is active or access is restricted Stop acquisition and recheck write access
Value is rejected despite fitting the sensor Current increment, mode or offset constraint Read fresh limits immediately before the write
Only the upper-left area appears Smaller dimensions retain the existing origin Read offsets and calculate the intended position
Readback is correct but preview looks unchanged Preview scaling or stale queued frames Inspect a newly acquired frame's dimensions and content
ROI changes after reopening Startup configuration or user-set loading overrides it Log configuration loads and feature writes in order
Compression setting is missing or rejected Unsupported feature or enumeration choice Inspect supported selections; do not use compression to reposition a crop

For rejected symbolic selections, follow the GenICam enumeration validation procedure. Increasing compression cannot restore scene content that acquisition cropping excluded.

Check camera and host compatibility before ordering

Browse area scan cameras or use the camera finder to shortlist the required interface and imaging characteristics. Then confirm ROI features, increments and persistence behavior in the documentation for the exact selection.

The LS-CMR-0053 is a GigE area scan camera. Its catalog listing does not establish support for every feature used in this procedure.

Area scan cameras12 MP GigE area scan camera, IMX226, 1/1.7" rolling shutter, 9 fps (LS-CMR-0053)LS-CMR-0053
Sensor format
1/1.7"
Lens mount
C-mount
Interface
GigE
Resolution
12 MP
$560.00View partBuild a system with it

The LS-CMR-0166 is a USB3 area scan camera. Confirm its supported Python integration and acquisition controls before choosing it for an existing application.

Area scan cameras12 MP USB3 area scan camera, IMX226, 1/1.7" rolling shutter, 30 fps, 4000 × 3000 resolution (LS-CMR-0166)LS-CMR-0166
Sensor format
1/1.7"
Interface
USB3
Resolution
12 MP
Shutter
Rolling
$560.00View partBuild a system with it

If comparing vision controllers, check compatibility with the camera SDK, operating system and intended acquisition interface. A camera connection alone does not establish that a particular Python binding is supported.

Do not replace a camera solely because Python attribute assignment fails. Establish whether the issue is feature support, binding syntax or configuration order first.

Preflight checklist and next step

Before commissioning, record these checks:

  • The requested change is acquisition cropping, not preview resizing.
  • The intended device opens with configuration access.
  • Geometry-affecting modes are selected before querying ROI limits.
  • Every dimension and offset passes its current range and increment checks.
  • Final readback and a newly acquired image agree.
  • Downstream calibration and coordinate transforms account for the crop origin.
  • Configuration failures leave acquisition stopped with a useful diagnostic.
  • Startup behavior is verified independently from persistent saving.

Once the procedure works, preserve the requested and accepted geometry in the configuration log. For hardware selection, start with the camera configurator. If ROI support or persistence remains unclear, use application support with your required dimensions, positioning tolerance and startup sequence.

Questions

Why does reducing camera width and height show only a corner?

Changing Width and Height normally selects a smaller acquisition rectangle rather than scaling the whole sensor image. If the offsets remain at the upper-left origin, that corner is what you receive. Set supported offsets to reposition the rectangle, or resize the full acquired image when you need to retain the entire scene.

Why does assigning camera.Width fail in Python?

The Python interface depends on the manufacturer's SDK and its feature binding. Some expose attributes, while others require node setters or name-based access. Open the device with configuration access, locate the acquisition feature map, and check feature availability and writability before choosing the documented write operation.

Should offsets be changed before image dimensions?

A common sequence is to stop acquisition, move independently writable offsets to their minimum, set the dimensions, and then apply the final offsets. This avoids conflicts with an existing crop position. Camera-specific dependencies can require another sequence, so read fresh limits and follow the documented procedure.

How can camera ROI settings survive a restart?

Keep the ROI in application configuration and reapply it during startup, or use a documented persistent user set when the camera supports one. Saving a set and selecting its power-up behavior can be separate operations. Verify settings after reopening the device and after an authorized power cycle.

Can compression replace ROI cropping when I need a smaller image?

Compression changes how image data is represented for transmission or storage; it does not move the acquisition rectangle. To retain the whole scene at smaller output dimensions, acquire the required scene and resize it, or evaluate supported sampling modes with their image-quality tradeoffs.