Filters#

All filters subclass VideoFilter and are callable: filtered = f(frame). The Q-prefixed variants add a parametertree control panel so they can be inserted into a QFilterBank.

Stateless filters also implement to_code() and participate in exportPipeline(), which generates a standalone filter.py from the rack’s current settings. Stateful filters that accumulate information across frames cannot be expressed as a single-frame function and are omitted from the export with a comment.

Calibration#

These filters correct systematic sensor non-uniformities so that pixel values reflect the true signal rather than hardware artefacts. Apply them early in the pipeline — typically as the first two filters — before any feature-detection or enhancement steps.

DarkFrameFilter subtracts a stored dark frame from every incoming image, removing thermal electrons, amplifier offset, and fixed-pattern noise. Click Capture with the shutter closed (or lens capped) to average nFrames frames into the dark reference. Click Reset to clear it and pass frames through unchanged.

FlatFieldFilter divides each frame by a stored flat field reference, correcting pixel-to-pixel quantum efficiency variation and lens vignetting. Click Capture under uniform illumination to record the reference; the mean is normalized to 1.0 so overall brightness is preserved. For best results, place this filter after DarkFrameFilter: the flat field is then captured from already-dark-subtracted frames and the correction is automatically dark-corrected.

Dark frame subtraction filter and companion Qt widget.

class QVideo.filters.darkframe.DarkFrameFilter(nFrames=16)[source]#

Bases: VideoFilter

Dark frame subtraction filter.

Subtracts a stored dark frame from every incoming image to remove camera baseline noise: thermal electrons, fixed-pattern noise, and amplifier offset.

Call capture() to start accumulating nFrames frames with no illumination. Once accumulated the mean is stored as the dark reference and captured is emitted. Every subsequent frame is dark-subtracted; negative values are clipped to zero.

Call reset() to clear the stored reference. Frames pass through unchanged until a new capture completes.

If the incoming frame shape changes after capture the reference is incompatible; get() returns the raw frame until a new capture is performed.

Parameters:

nFrames (int) – Number of frames to average during capture. Default: 16.

captured#

str = …, revision: int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

property nFrames: int#

Number of frames averaged during capture (≥ 1).

property isCapturing: bool#

True while a dark frame capture is in progress.

capture()[source]#

Start accumulating a dark frame.

Resets the accumulator and counts down nFrames calls to add(). captured is emitted on completion.

Return type:

None

reset()[source]#

Clear the stored dark frame and any ongoing capture.

Frames pass through unchanged until a new capture completes.

Return type:

None

add(image)[source]#

Incorporate a new frame into the filter state.

During a capture, accumulates frames into a running sum. When the target count is reached the mean is stored as the dark frame and captured is emitted.

Parameters:

image (Image) – Input frame.

Return type:

None

get()[source]#

Return the dark-subtracted frame.

Returns None before the first add(), the raw frame if no dark reference is stored or if the frame shape does not match the reference, and the clipped dark-subtracted frame otherwise.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]] | None

Returns:

Image or None

class QVideo.filters.darkframe.QDarkFrameFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for DarkFrameFilter with capture controls.

A checkable group box with a frames spinbox setting how many frames are averaged, a Capture button to start accumulation, and a Reset button to clear the stored dark frame. The Capture button is disabled during accumulation and re-enabled on completion.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Dark Frame'#
display_category: str = 'Calibration'#

Flat field normalization filter and companion Qt widget.

class QVideo.filters.flatfield.FlatFieldFilter(nFrames=16)[source]#

Bases: VideoFilter

Flat field normalization filter.

Corrects pixel-wise sensitivity variation by dividing each frame by a stored flat field reference. The reference is the mean of nFrames frames captured under uniform illumination, normalized so that its mean equals 1.0. Division restores uniform response across the sensor.

For best results, place this filter after DarkFrameFilter in the pipeline. When dark-subtracted frames are used during the reference capture the flat field is automatically dark-corrected, and subsequent frames arrive already dark-subtracted.

Call capture() to start accumulating the flat field reference. Call reset() to clear it. Frames pass through unchanged until a reference is captured.

Pixels where the normalized flat field is zero are passed through without correction.

If the incoming frame shape does not match the stored reference get() returns the raw frame until a new capture is performed.

Emits captured when a new flat field capture completes.

Parameters:

nFrames (int) – Number of frames to average during capture. Default: 16.

captured#

str = …, revision: int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

property nFrames: int#

Number of frames averaged during capture (≥ 1).

property isCapturing: bool#

True while a flat field capture is in progress.

capture()[source]#

Start accumulating a flat field reference.

Resets the accumulator and counts down nFrames calls to add(). captured is emitted on completion.

Return type:

None

reset()[source]#

Clear the stored flat field reference and any ongoing capture.

Frames pass through unchanged until a new capture completes.

Return type:

None

add(image)[source]#

Incorporate a new frame into the filter state.

During a capture, accumulates frames into a running sum. When the target count is reached the mean is normalized (divided by its own mean) and stored. If the mean is zero, no reference is stored. captured is emitted on completion.

Parameters:

image (Image) – Input frame.

Return type:

None

get()[source]#

Return the flat-field-corrected frame.

Returns None before the first add(), the raw frame if no reference is stored or if the frame shape does not match the reference, and the corrected (clipped) frame otherwise. Pixels where the flat field is zero pass through unchanged.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]] | None

Returns:

Image or None

class QVideo.filters.flatfield.QFlatFieldFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for FlatFieldFilter with capture controls.

A checkable group box with a frames spinbox setting how many frames are averaged, a Capture button to start accumulation, and a Reset button to clear the stored reference. The Capture button is disabled during accumulation and re-enabled on completion.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Flat Field'#
display_category: str = 'Calibration'#

Median background subtraction#

The remedian algorithm [R90] computes a pixel-wise median over a sliding window of 3 ** order frames using only two frame buffers per recursion level. Median produces a new estimate every third frame; MoMedian produces one on every frame by rolling the buffer.

[R90]

P.J. Rousseeuw and G.W. Bassett Jr., “The remedian: a robust averaging method for large data sets”, Journal of the American Statistical Association, 85(409):97–104, 1990.

Batch median-of-medians background estimator (remedian algorithm).

class QVideo.filters.median.Median(order=1, data=None)[source]#

Bases: _MedianBase

Fast median-of-medians background estimator.

Computes a running pixel-wise median over 3 ** order frames using a recursive median-of-three algorithm that requires only two frame buffers per level.

Parameters:
  • order (int) – Recursion depth. The median is computed over 3 ** order frames. Default: 1 (median of 3 frames).

  • data (Image or None) – Optional seed frame used to pre-allocate internal buffers. If None the buffers are allocated on the first call to add(). Default: None.

Notes

Results are only available once ready() returns True, which requires at least 3 ** order frames to have been added. Before that point get() returns whatever seed data was provided (or None).

The reset() method clears all buffers and resets the ready flag so that the estimator starts fresh without reallocating memory.

References

P.J. Rousseeuw and G.W. Bassett Jr., “The remedian: a robust averaging method for large data sets”, Journal of the American Statistical Association, 85(409):97–104, 1990. doi:10.1080/01621459.1990.10475311

add(data)[source]#

Incorporate a new frame into the median estimate.

Resets the ready flag at the start of each call so that ready() reflects only whether this call produced a new estimate.

Parameters:

data (Image) – Input frame. If the shape differs from the previously seen shape, the internal buffers are reallocated.

Return type:

None

ready()[source]#

Return True if the most recent add() produced a new estimate.

The flag is reset at the start of each add() call and set again only if that call completes a new median computation. Calling get() does not affect this flag.

Return type:

bool

Returns:

boolTrue if the last add() yielded a fresh estimate.

Streaming median-of-medians background estimator (rolling remedian).

class QVideo.filters.momedian.MoMedian(order=1, data=None)[source]#

Bases: _MedianBase

Streaming median-of-medians background estimator.

Computes a running pixel-wise median over 3 ** order frames using a rolling two-frame buffer. Unlike Median, a new estimate is produced on every frame (not every third), at the cost of a slightly less accurate result for small order.

Parameters:
  • order (int) – Recursion depth. The estimate draws from 3 ** order frames. Default: 1 (median of 3 frames).

  • data (Image or None) – Optional seed frame used to pre-allocate internal buffers. If None the buffers are allocated on the first call to add(). Default: None.

Notes

MoMedian is a rolling variant of the remedian [R90]: rather than waiting for a complete triplet, it uses the two most recently stored frames together with the current frame to produce a new estimate on every call. This reduces latency at the cost of slight accuracy loss relative to the strict remedian.

References

[R90]

P.J. Rousseeuw and G.W. Bassett Jr., “The remedian: a robust averaging method for large data sets”, Journal of the American Statistical Association, 85(409):97–104, 1990. doi:10.1080/01621459.1990.10475311

add(data)[source]#

Incorporate a new frame into the median estimate.

Produces a new estimate on every call using a rolling two-frame buffer.

Parameters:

data (Image) – Input frame. If the shape differs from the previously seen shape, the internal buffers are reallocated.

Return type:

None

class QVideo.filters.momedian.QMoMedian(parent=None)[source]#

Bases: QVideoFilter

Widget for MoMedian with an order spinbox.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Running Median'#
display_category: str = 'Background'#

Running mean (EMA)#

MoMean maintains a per-pixel exponential moving average (EMA) of the incoming frames:

\[\hat{B}_t = \alpha\,I_t + (1 - \alpha)\,\hat{B}_{t-1}\]

where α controls how quickly the estimate tracks changes. A small α produces a heavily smoothed, slow-responding background; α = 1 reduces to a passthrough. The effective time constant in frames is approximately 1 / α. Unlike the remedian estimators, a new estimate is available on every frame with no warm-up period.

The companion QMoMean widget exposes an α spinbox.

Exponential moving-average background estimator and companion Qt widget.

class QVideo.filters.momean.MoMean(alpha=0.1)[source]#

Bases: VideoFilter

Exponential moving-average (EMA) background estimator.

Maintains a per-pixel running average that weights each incoming frame by alpha and the existing estimate by (1 − alpha):

\[\hat{B}_t = \alpha\,I_t + (1 - \alpha)\,\hat{B}_{t-1}\]

where \(I_t\) is the current frame and \(\hat{B}\) is the background estimate. A small alpha produces a slow-responding, heavily smoothed estimate; alpha = 1 reduces to a passthrough.

The effective time constant in frames is approximately \(1 / \alpha\).

Parameters:

alpha (float) – EMA weight on the incoming frame. Clamped to (0, 1]. Default: 0.1.

property alpha: float#

EMA weight on the incoming frame, in (0, 1].

reset()[source]#

Clear the accumulator and restart the estimator.

Return type:

None

add(data)[source]#

Incorporate a new frame into the running average.

Parameters:

data (Image) – Input frame. If the shape differs from the previous frame the accumulator is re-initialised.

Return type:

None

get()[source]#

Return the current background estimate.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]] | None

Returns:

Image or None – uint8 estimate, or None if no frames have been added.

class QVideo.filters.momean.QMoMean(parent=None)[source]#

Bases: QVideoFilter

Widget for MoMean with an alpha spinbox.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Running Mean'#
display_category: str = 'Background'#

Normalisation#

These filters divide each incoming frame by a median background estimate, removing fixed-pattern noise and illumination gradients to reveal foreground features. Normalize uses the batch Median estimator; SmoothNormalize uses the rolling MoMedian estimator for lower latency.

Background-normalization filters built on median background estimation.

class QVideo.filters.normalize.Normalize(*args, scale=True, mean=100.0, darkcount=0, **kwargs)[source]#

Bases: _NormalizeMixin, Median

Normalize frames against a median background estimate.

Combines _NormalizeMixin with Median to produce a background-subtracted, normalized image stream. Background estimation uses the median-of-three algorithm; a new background estimate is available every 3 ** order frames.

Parameters:
  • order (int) – Recursion depth for the median estimator. Default: 1.

  • scale (bool) – Scale normalized output to mean. Default: True.

  • mean (float) – Target mean after scaling. Default: 100.0.

  • darkcount (int) – Camera dark-count offset. Default: 0.

class QVideo.filters.normalize.SmoothNormalize(*args, scale=True, mean=100.0, darkcount=0, **kwargs)[source]#

Bases: _NormalizeMixin, MoMedian

Normalize frames against a streaming median background estimate.

Combines _NormalizeMixin with MoMedian to produce a background-subtracted, normalized image stream. Background estimation uses the rolling median-of-three algorithm; a new estimate is produced on every frame.

Parameters:
  • order (int) – Recursion depth for the median estimator. Default: 1.

  • scale (bool) – Scale normalized output to mean. Default: True.

  • mean (float) – Target mean after scaling. Default: 100.0.

  • darkcount (int) – Camera dark-count offset. Default: 0.

Sample-and-hold background#

SampleHold extends Normalize with a hold mechanism: it accumulates frames until the background estimate converges, then freezes it and switches to normalising foreground frames against the held estimate. Clicking Reset in the companion widget triggers a fresh accumulation pass, which is useful after scene changes.

Sample-and-hold background normalization filter and companion Qt widget.

class QVideo.filters.samplehold.SampleHold(*args, **kwargs)[source]#

Bases: Normalize

reset()[source]#

Restart background accumulation.

Resets the frame counter so that the next 3 ** order frames are used to build a fresh background estimate.

Return type:

None

get()[source]#

Return the current filter output.

While the background is still being accumulated, returns the raw (dark-count-corrected) frame so the display stays live. Once accumulation is complete, returns the normalized frame.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]] | None

Returns:

Image or None – Raw frame during accumulation, normalized frame afterwards, or None if called before the first add().

add(image)[source]#

Incorporate a new frame into the filter state.

While the frame counter is positive the frame is passed to the parent Normalize accumulator to build the background estimate. Once the counter reaches zero the frame is stored as the foreground (normalized against the held background).

If the frame shape changes reset() is called automatically.

Parameters:

image (Image) – Input frame.

Return type:

None

class QVideo.filters.samplehold.QSampleHold(parent=None)[source]#

Bases: QVideoFilter

Widget for SampleHold with order buttons and a Reset button.

Wraps SampleHold in a checkable group box. Three radio buttons select the accumulation order (1, 2, or 3), corresponding to background estimates built from 3, 9, or 27 frames respectively. The Reset button triggers reset(), causing the filter to re-sample the background using the selected order.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Sample and Hold'#
display_category: str = 'Background'#
setOrder(checked, order)[source]#

Set the accumulation order and restart background sampling.

Only acts when checked is True to avoid double-firing on radio button deselection. Setting a new order clears the estimator and restarts accumulation immediately.

Parameters:
  • checked (bool) – Whether the button is being selected (True) or deselected (False).

  • order (int) – Accumulation order (1, 2, or 3).

Return type:

None

reset(_checked=False)[source]#

Reset the background estimate.

Connected to the Reset button. The _checked argument is the toggle state emitted by QPushButton and is ignored.

Parameters:

_checked (bool) – Unused toggle state from the button signal.

Return type:

None

Gamma correction#

GammaFilter applies the power-law transform output = (input / 255)^γ × 255 to every pixel using a 256-entry look-up table built once when gamma changes. γ < 1 lifts shadows; γ > 1 deepens them; γ = 1 is the identity. Because the LUT is applied by cv2.LUT, per-frame cost is independent of image size. The same table is applied to every channel, preserving colour balance. Supports pipeline export.

Gamma intensity-correction filter and companion Qt widget.

class QVideo.filters.gamma.GammaFilter(gamma=1.0)[source]#

Bases: VideoFilter

Gamma intensity correction.

Applies the power-law transform

\[\text{output} = \left(\frac{\text{input}}{255}\right)^{\gamma} \times 255\]

to every pixel. γ < 1 brightens the image (lifts shadows); γ > 1 darkens it (deepens shadows); γ = 1 is the identity.

The transform is implemented as a 256-entry look-up table built once when gamma changes, so per-frame cost is a single table lookup regardless of image size. The same LUT is applied to every channel, preserving color balance.

Parameters:

gamma (float) – Power-law exponent. Must be ≥ 0.1. Default: 1.0.

property gamma: float#

Power-law exponent (≥ 0.1); LUT is rebuilt on assignment.

get()[source]#

Return the gamma-corrected frame.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]] | None

Returns:

Image or None – Corrected uint8 image, or None if no frame has been added.

to_code()[source]#

Return a FilterCode fragment for pipeline export.

Stateless filters implement this to enable exportPipeline(). Stateful filters (those that accumulate state across frames) return None to indicate they cannot be expressed as a single-frame pure function.

Return type:

FilterCode

Returns:

FilterCode or None – Code fragment, or None if export is not supported.

class QVideo.filters.gamma.QGammaFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for GammaFilter with a gamma spinbox.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Gamma Correction'#
display_category: str = 'Preprocessing'#

Exposure correction#

ExposureFilter provides three tone-mapping methods selectable at runtime.

Log compresses dynamic range via a logarithmic curve — log(1 + p) / log(256) — lifting shadow detail without clipping highlights. No parameters.

Sigmoid applies a smooth S-curve centred at cutoff with steepness gain. Low gain gives a gentle contrast boost; high gain approaches hard clipping.

CLAHE (Contrast-Limited Adaptive Histogram Equalization) equalises local contrast within tile_size × tile_size tiles, capping amplification at clip_limit to suppress noise amplification. On colour input, CLAHE is applied to the L channel in LAB colour space so hue and saturation are preserved. All three methods support pipeline export.

Exposure correction filters (Log, Sigmoid, CLAHE) and companion Qt widget.

class QVideo.filters.exposure.ExposureFilter(method='Log', cutoff=128.0, gain=10.0, clip_limit=2.0, tile_size=8)[source]#

Bases: AsyncVideoFilter

Exposure tone-mapping with three selectable methods.

Log compresses the dynamic range via a logarithmic curve, lifting shadows without clipping highlights. No parameters.

Sigmoid applies a smooth S-curve centred at cutoff with steepness gain. Low gain gives a gentle contrast boost; high gain approaches hard clipping.

CLAHE (Contrast-Limited Adaptive Histogram Equalization) equalises local contrast within tile_size × tile_size tiles, capping amplification at clip_limit to suppress noise. On colour input, CLAHE is applied to the L channel in LAB colour space so hue and saturation are preserved.

Computation runs in a background thread via AsyncVideoFilter, keeping the GUI responsive even for large frames.

Parameters:
  • method (str) – One of 'Log', 'Sigmoid', or 'CLAHE'. Default: 'Log'.

  • cutoff (float) – Sigmoid midpoint [0, 255]. Default: 128.0.

  • gain (float) – Sigmoid steepness (≥ 0.1). Default: 10.0.

  • clip_limit (float) – CLAHE contrast-limit threshold (≥ 0.1). Default: 2.0.

  • tile_size (int) – CLAHE grid cell size in pixels (≥ 1). Default: 8.

METHODS = ('Log', 'Sigmoid', 'CLAHE')#
property method: str#

'Log', 'Sigmoid', or 'CLAHE'.

Type:

Tone-mapping method

property cutoff: float#

Sigmoid midpoint [0, 255].

property gain: float#

Sigmoid steepness (≥ 0.1).

property clip_limit: float#

CLAHE contrast-limit threshold (≥ 0.1); rebuilds CLAHE object.

property tile_size: int#

CLAHE grid cell size in pixels (≥ 1); rebuilds CLAHE object.

process(image)[source]#

Apply the selected tone-mapping method to image.

Called in the background thread.

Parameters:

image (Image) – Input uint8 frame.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]]

Returns:

Image – Tone-mapped uint8 frame.

to_code()[source]#

Return a FilterCode fragment for pipeline export.

Stateless filters implement this to enable exportPipeline(). Stateful filters (those that accumulate state across frames) return None to indicate they cannot be expressed as a single-frame pure function.

Return type:

FilterCode

Returns:

FilterCode or None – Code fragment, or None if export is not supported.

class QVideo.filters.exposure.QExposureFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for ExposureFilter with a method selector and context-sensitive parameter spinboxes.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Exposure'#
display_category: str = 'Preprocessing'#

Difference of Gaussians#

DoGFilter implements the Difference-of-Gaussians (DoG) bandpass filter. It subtracts a wide Gaussian blur (high_sigma) from a narrow one (low_sigma), suppressing both slowly-varying background and high-frequency noise. The result is displayed as the absolute value scaled to uint8, so both positive and negative excursions appear bright.

DoG is a standard preprocessing step for particle tracking and fluorescence microscopy: it isolates features at the scale set by low_sigma while removing background and pixel noise. Colour input is converted to grayscale before filtering. Supports pipeline export.

Difference-of-Gaussians bandpass filter and companion Qt widget.

class QVideo.filters.dog.DoGFilter(low_sigma=1.0, high_sigma=3.0)[source]#

Bases: VideoFilter

Difference-of-Gaussians (DoG) bandpass filter.

Subtracts a wide Gaussian blur from a narrow one, suppressing both slowly-varying background (low_sigma) and high-frequency noise (high_sigma sets the noise cutoff). The result is displayed as the absolute value scaled to uint8, so both positive and negative excursions appear bright.

DoG is the standard preprocessing step for particle tracking and fluorescence microscopy: it isolates features at the scale set by low_sigma while removing background and pixel noise.

Color input is converted to grayscale before filtering.

Parameters:
  • low_sigma (float) – Standard deviation of the narrower Gaussian [pixels]. Controls the smallest feature scale retained. Must be < high_sigma. Default: 1.0.

  • high_sigma (float) – Standard deviation of the wider Gaussian [pixels]. Controls the largest background scale removed. Must be > low_sigma. Default: 3.0.

property low_sigma: float#

Narrow Gaussian σ [pixels]; must be < high_sigma.

property high_sigma: float#

Wide Gaussian σ [pixels]; must be > low_sigma.

get()[source]#

Return the DoG-filtered frame.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]] | None

Returns:

Image or None – uint8 image of the absolute DoG response, or None if no frame has been added.

to_code()[source]#

Return a FilterCode fragment for pipeline export.

Stateless filters implement this to enable exportPipeline(). Stateful filters (those that accumulate state across frames) return None to indicate they cannot be expressed as a single-frame pure function.

Return type:

FilterCode

Returns:

FilterCode or None – Code fragment, or None if export is not supported.

class QVideo.filters.dog.QDoGFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for DoGFilter with low and high sigma spinboxes.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Difference of Gaussians'#
display_category: str = 'Preprocessing'#

Unsharp mask#

UnsharpFilter sharpens each frame by subtracting a Gaussian-blurred copy (radius) scaled by amount from the original, implemented as cv2.addWeighted so the result is clipped to [0, 255] without overflow. amount = 0 is a no-op; amount = 1 gives a standard unsharp mask; higher values over-sharpen. Accepts both grayscale and colour input. Supports pipeline export.

Unsharp masking filter and companion Qt widget.

class QVideo.filters.unsharp.UnsharpFilter(radius=2.0, amount=1.0)[source]#

Bases: VideoFilter

Unsharp mask sharpening.

Computes a Gaussian-blurred copy of the frame and blends it with the original to emphasise high-frequency detail:

\[\text{output} = (1 + \alpha)\,\text{image} - \alpha\,\text{blur}(\text{image},\,\sigma)\]

where σ (radius) sets the blur width and α (amount) controls sharpening strength. cv2.addWeighted is used so the result is clipped to [0, 255] and returned as uint8.

Parameters:
  • radius (float) – Standard deviation of the Gaussian blur [pixels] (≥ 0.1). Larger values sharpen broader features. Default: 2.0.

  • amount (float) – Sharpening strength (≥ 0.0). 0 is a no-op; 1 gives a standard unsharp mask; higher values over-sharpen. Default: 1.0.

property radius: float#

Gaussian blur σ [pixels] (≥ 0.1).

property amount: float#

Sharpening strength (≥ 0.0).

get()[source]#

Return the sharpened frame.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]] | None

Returns:

Image or None – uint8 sharpened image, or None if no frame has been added.

to_code()[source]#

Return a FilterCode fragment for pipeline export.

Stateless filters implement this to enable exportPipeline(). Stateful filters (those that accumulate state across frames) return None to indicate they cannot be expressed as a single-frame pure function.

Return type:

FilterCode

Returns:

FilterCode or None – Code fragment, or None if export is not supported.

class QVideo.filters.unsharp.QUnsharpFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for UnsharpFilter with radius and amount spinboxes.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Unsharp Mask'#
display_category: str = 'Preprocessing'#

Smoothing#

SmoothingFilter applies OpenCV smoothing with an adjustable odd-pixel kernel. Three methods are available:

  • 'box' (cv2.blur) — uniform box average; fastest of the three, O(N) cost independent of kernel size.

  • 'gaussian' (cv2.GaussianBlur) — weighted average with a Gaussian kernel; effective against additive Gaussian noise.

  • 'median' (cv2.medianBlur) — replaces each pixel with the neighbourhood median; excels at removing salt-and-pepper noise while preserving edges.

The QSmoothingFilter widget exposes a method selector combobox and a width spinbox. Supports pipeline export.

Smoothing filter with selectable method and companion Qt widget.

class QVideo.filters.smoothing.SmoothingFilter(width=15, method='gaussian')[source]#

Bases: AsyncVideoFilter

Smoothing filter supporting box, Gaussian, and median blur.

Parameters:
  • width (int) – Kernel width in pixels. Must be odd and at least 1; even values are rounded up to the next odd integer. Default: 15.

  • method (str) – Smoothing method: 'box', 'gaussian', or 'median'. Default: 'gaussian'.

Notes

OpenCV requires an odd, positive kernel size for GaussianBlur and medianBlur. blur (box filter) accepts any positive size, but the width setter enforces odd values uniformly across all methods.

For Gaussian blur, sigma is set to 0, which instructs OpenCV to derive it from the kernel size.

METHODS = ('box', 'gaussian', 'median')#
property width: int#

Kernel width [pixels], always odd and at least 1.

property method: str#

'box', 'gaussian', or 'median'.

Type:

Smoothing method

to_code()[source]#

Return a FilterCode fragment for pipeline export.

Stateless filters implement this to enable exportPipeline(). Stateful filters (those that accumulate state across frames) return None to indicate they cannot be expressed as a single-frame pure function.

Return type:

FilterCode

Returns:

FilterCode or None – Code fragment, or None if export is not supported.

process(image)[source]#

Return the smoothed frame.

Called in the background thread.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]]

Returns:

Image – Smoothed version of image.

class QVideo.filters.smoothing.QSmoothingFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for SmoothingFilter with method selector and width spinbox.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Smoothing'#
display_category: str = 'Preprocessing'#

Dejitter (video stabilization)#

DejitterFilter corrects translational camera jitter frame-by-frame using FFT-based phase correlation (cv2.phaseCorrelate with a Hanning window) to estimate the sub-pixel shift between each frame and a reference image, then applies the inverse translation via cv2.warpAffine.

Two reference-update modes are supported:

  • Static — the reference is fixed to the first frame seen after construction or reset. Subsequent frames are aligned to that origin. Best for suppressing mechanical vibration around a fixed position.

  • Rolling — the reference is updated each frame by an exponential moving average (weight α on the new frame), so it tracks slow drift while only fast jitter is corrected. Best for long acquisitions where deliberate stage motion should be preserved.

Computation runs in a background thread via AsyncVideoFilter. The companion QDejitterFilter widget exposes a mode selector, an α spinbox (shown only in Rolling mode), and a Reset button to reseed the reference.

Dejitter filter using phase-correlation image stabilization.

class QVideo.filters.dejitter.DejitterFilter(mode='static', alpha=0.05)[source]#

Bases: AsyncVideoFilter

Translation-only video stabilizer using phase correlation.

Estimates the per-frame shift of the camera relative to a reference image via cv2.phaseCorrelate (FFT-based cross-correlation) and corrects it with cv2.warpAffine.

Two reference-update modes are supported:

  • static: the reference is the first frame seen after construction or reset(). All subsequent frames are aligned to that fixed origin. Best for suppressing mechanical vibration around a fixed position.

  • rolling: the reference is updated each frame by an exponential moving average (weight alpha on the new frame). The reference therefore tracks slow drift, so only fast jitter is corrected. Best for long acquisitions where deliberate stage motion should be preserved.

A Hanning window is applied before phase correlation to reduce spectral leakage.

Parameters:
  • mode (str) – Reference update mode: 'static' or 'rolling'. Default: 'static'.

  • alpha (float) – EMA weight on the incoming frame for rolling-mode reference updates. Clamped to (0, 1]. Ignored in static mode. Default: 0.05.

MODES = ('static', 'rolling')#
property mode: str#

Reference update mode; one of MODES.

property alpha: float#

EMA weight on incoming frame for rolling reference, in (0, 1].

reset()[source]#

Clear the reference frame and restart stabilization.

Return type:

None

process(image)[source]#

Estimate and correct the translational shift of image.

Called in the background thread. The first frame after construction or reset() seeds the reference and is returned unchanged.

Parameters:

image (Image) – Input frame (grayscale or BGR uint8).

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]]

Returns:

Image – Stabilized frame with the same shape and dtype as image.

class QVideo.filters.dejitter.QDejitterFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for DejitterFilter with mode selector, alpha spinbox, and a reset button.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Dejitter'#
display_category: str = 'Preprocessing'#

Edge detection#

Three edge-detection filters are available, each suited to different imaging conditions. All accept color or grayscale input and return a uint8 edge map.

CannyEdgeFilter applies OpenCV’s multi-stage Canny detector [C86]. Two hysteresis thresholds (low and high) control which gradient-magnitude edges are retained; a 2:1 or 3:1 high-to-low ratio is recommended for typical scientific images. Canny produces a clean binary edge map and is the best general-purpose choice. Supports pipeline export.

SobelSobelFilter computes a first-order directional derivative using the Sobel operator. Three modes are available: Horizontal (∂/∂x), Vertical (∂/∂y), and Magnitude (Euclidean magnitude √(Gx² + Gy²), clipped to [0, 255]). The kernel size k is odd and in {1, 3, 5, 7}. Sobel is well suited to extracting directional gradient information or computing gradient-magnitude images for further analysis. Supports pipeline export.

LaplacianLaplacianFilter applies the discrete Laplacian operator (∇²), returning the absolute value as a uint8 image. An optional Gaussian pre-blur with standard deviation σ reduces noise sensitivity; setting σ > 0 implements the Laplacian-of-Gaussian (LoG) operator commonly used to detect blob-like features at a scale set by σ. Supports pipeline export.

[C86]

J. Canny, ‘A computational approach to edge detection,’ IEEE Transactions on Pattern Analysis and Machine Intelligence 8, 679–698 (1986).

Canny edge-detection filter and companion Qt widget.

class QVideo.filters.edge.EdgeFilter(low=50, high=150)[source]#

Bases: VideoFilter

Canny edge detector.

Converts color input to grayscale, then applies OpenCV’s Canny edge-detection algorithm.

Parameters:
  • low (int) – Lower hysteresis threshold. Must be at least 1 and strictly less than high. Default: 50.

  • high (int) – Upper hysteresis threshold. Must be at least 2 and strictly greater than low. Default: 150.

Notes

Both thresholds are passed directly to cv2.Canny(). OpenCV recommends a 2:1 or 3:1 high-to-low ratio for typical images.

property low: int#

Lower Canny threshold (≥ 1, < high).

property high: int#

Upper Canny threshold (≥ 2, > low).

add(image)[source]#

Convert color input to grayscale and store the result.

Parameters:

image (Image) – Input frame. 3-D (color) arrays are converted to grayscale; 2-D arrays are stored unchanged.

Return type:

None

to_code()[source]#

Return a FilterCode fragment for pipeline export.

Stateless filters implement this to enable exportPipeline(). Stateful filters (those that accumulate state across frames) return None to indicate they cannot be expressed as a single-frame pure function.

Return type:

FilterCode

Returns:

FilterCode or None – Code fragment, or None if export is not supported.

get()[source]#

Return the Canny edge map of the stored frame.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]] | None

Returns:

Image or None – Edge map, or None if no frame has been added yet.

class QVideo.filters.edge.QEdgeFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for EdgeFilter with low- and high-threshold spinboxes.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Canny'#
display_category: str = 'Edge Detection'#

Sobel gradient edge-detection filter and companion Qt widget.

class QVideo.filters.sobel.SobelFilter(direction='Magnitude', ksize=3)[source]#

Bases: VideoFilter

Sobel edge detector with horizontal, vertical, and magnitude modes.

Converts each frame to grayscale, then applies the Sobel operator.

  • Horizontal: first-order x-derivative (∂/∂x), converted to uint8.

  • Vertical: first-order y-derivative (∂/∂y), converted to uint8.

  • Magnitude: Euclidean magnitude of the (∂/∂x, ∂/∂y) gradient, clipped to [0, 255].

Parameters:
  • direction (str) – One of 'Horizontal', 'Vertical', 'Magnitude'. Default: 'Magnitude'.

  • ksize (int) – Sobel kernel size [pixels]. Must be odd and in {1, 3, 5, 7}. Default: 3.

DIRECTIONS = ('Horizontal', 'Vertical', 'Magnitude')#
property direction: str#

Gradient mode; one of DIRECTIONS.

property ksize: int#

Sobel kernel size [pixels], always odd and in {1, 3, 5, 7}.

to_code()[source]#

Return a FilterCode fragment for pipeline export.

Stateless filters implement this to enable exportPipeline(). Stateful filters (those that accumulate state across frames) return None to indicate they cannot be expressed as a single-frame pure function.

Return type:

FilterCode

Returns:

FilterCode or None – Code fragment, or None if export is not supported.

get()[source]#

Return the Sobel edge map of the stored frame.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]] | None

Returns:

Image or None – uint8 edge map, or None if no frame has been added.

class QVideo.filters.sobel.QSobelFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for SobelFilter with direction selector and kernel size spinbox.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Sobel'#
display_category: str = 'Edge Detection'#

Laplacian edge-detection filter and companion Qt widget.

class QVideo.filters.laplacian.LaplacianFilter(ksize=3, sigma=0.0)[source]#

Bases: VideoFilter

Laplacian (∇²) edge detector with optional Gaussian pre-blur.

Converts each frame to grayscale, optionally applies a Gaussian blur to reduce noise sensitivity, then computes the discrete Laplacian. The absolute value is returned as a uint8 image; edges appear bright at intensity transitions.

Setting sigma > 0 implements the Laplacian-of-Gaussian (LoG) operator.

Parameters:
  • ksize (int) – Laplacian kernel size [pixels]. Must be odd and ≥ 1. Default: 3.

  • sigma (float) – Standard deviation of the optional Gaussian pre-blur [pixels]. 0 skips blurring. Default: 0.

property ksize: int#

Laplacian kernel size [pixels], always odd and ≥ 1.

property sigma: float#

Gaussian pre-blur standard deviation [pixels]; 0 skips blur.

to_code()[source]#

Return a FilterCode fragment for pipeline export.

Stateless filters implement this to enable exportPipeline(). Stateful filters (those that accumulate state across frames) return None to indicate they cannot be expressed as a single-frame pure function.

Return type:

FilterCode

Returns:

FilterCode or None – Code fragment, or None if export is not supported.

get()[source]#

Return the Laplacian edge map of the stored frame.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]] | None

Returns:

Image or None – uint8 edge map, or None if no frame has been added.

class QVideo.filters.laplacian.QLaplacianFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for LaplacianFilter with kernel size and sigma spinboxes.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Laplacian'#
display_category: str = 'Edge Detection'#

RGB channel selection#

RGBFilter extracts a single color channel (Red, Green, or Blue) from an RGB frame, discarding the other two. Grayscale input passes through unchanged. The companion widget exposes the channel choice as three radio buttons. Supports pipeline export.

RGB color-channel selection filter and companion Qt widget.

class QVideo.filters.rgb.RGBFilter(channel=0)[source]#

Bases: VideoFilter

Extracts a single color channel from an RGB image.

For grayscale (2-D) input the frame is passed through unchanged regardless of the channel setting.

Parameters:

channel (int) – Channel index to extract: 0 = Red, 1 = Green, 2 = Blue. Default: 0.

property channel: int#

Channel index (0=Red, 1=Green, 2=Blue).

to_code()[source]#

Return a FilterCode fragment for pipeline export.

Stateless filters implement this to enable exportPipeline(). Stateful filters (those that accumulate state across frames) return None to indicate they cannot be expressed as a single-frame pure function.

Return type:

FilterCode

Returns:

FilterCode or None – Code fragment, or None if export is not supported.

add(image)[source]#

Extract the selected channel and store the result.

Parameters:

image (Image) – Input frame. 2-D arrays are stored unchanged; 3-D arrays have the selected channel extracted.

Return type:

None

class QVideo.filters.rgb.QRGBFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for RGBFilter with Red/Green/Blue radio buttons.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Color Channel'#
display_category: str = 'Preprocessing'#
setChannel(checked, channel)[source]#

Set the active color channel.

Called on every radio button toggle; only acts when checked is True to avoid updating the filter on the deselection signal of the previous button.

Parameters:
  • checked (bool) – Whether the button is being selected (True) or deselected (False).

  • channel (int) – Channel index corresponding to the toggled button.

Return type:

None

Threshold#

ThresholdFilter converts each frame to grayscale and applies a binary threshold, producing a black-and-white mask. Four methods are available:

  • Global — pixels above a fixed level are set to 255; all others to 0.

  • Otsu — the threshold is chosen automatically to minimise intra-class intensity variance [O79]; the level parameter is ignored.

  • Adaptive Mean — the threshold at each pixel is the mean intensity of a block × block neighbourhood minus a constant C.

  • Adaptive Gaussian — like Adaptive Mean, but using a Gaussian-weighted neighbourhood mean.

The companion QThresholdFilter widget exposes a method selector combobox; parameter spinboxes appear and disappear depending on the selected method. Supports pipeline export.

[O79]

N. Otsu, ‘A threshold selection method from gray-level histograms,’ IEEE Transactions on Systems, Man, and Cybernetics 9, 62–66 (1979).

Binary threshold filter with global, Otsu, and adaptive methods.

class QVideo.filters.threshold.ThresholdFilter(threshold=127, method='Global', block_size=11, C=2)[source]#

Bases: VideoFilter

Binary threshold filter supporting global, Otsu, and adaptive methods.

Converts each frame to a binary image using one of four methods:

  • Global: pixels above threshold become 255, others become 0.

  • Otsu: threshold level chosen automatically to minimise intra-class variance (Otsu 1979). The threshold parameter is ignored.

  • Adaptive Mean: threshold at each pixel is the mean of the block_size × block_size neighbourhood minus C.

  • Adaptive Gaussian: threshold at each pixel is the Gaussian-weighted mean of the neighbourhood minus C.

Colour input is converted to grayscale before thresholding.

Parameters:
  • threshold (int) – Global threshold value [0, 255]. Default: 127.

  • method (str) – One of 'Global', 'Otsu', 'Adaptive Mean', 'Adaptive Gaussian'. Default: 'Global'.

  • block_size (int) – Neighbourhood size for adaptive methods [pixels]. Must be odd and ≥ 3. Default: 11.

  • C (int) – Constant subtracted from the adaptive mean. Default: 2.

METHODS = ('Global', 'Otsu', 'Adaptive Mean', 'Adaptive Gaussian')#
property threshold: int#

Global threshold value [0, 255], clamped on assignment.

property method: str#

Thresholding method; one of METHODS.

property block_size: int#

Adaptive neighbourhood size [pixels], always odd and ≥ 3.

property C: int#

Constant subtracted from the adaptive neighbourhood mean.

to_code()[source]#

Return a FilterCode fragment for pipeline export.

Stateless filters implement this to enable exportPipeline(). Stateful filters (those that accumulate state across frames) return None to indicate they cannot be expressed as a single-frame pure function.

Return type:

FilterCode

Returns:

FilterCode or None – Code fragment, or None if export is not supported.

get()[source]#

Return the thresholded frame.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]] | None

Returns:

Image or None – Binary uint8 image, or None if no frame has been added.

class QVideo.filters.threshold.QThresholdFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for ThresholdFilter with method selector and context-sensitive parameter spinboxes.

Shows a method combobox and, depending on the selected method:

  • Global: a level spinbox [0, 255].

  • Otsu: no extra controls (threshold is computed automatically).

  • Adaptive Mean / Adaptive Gaussian: block (neighbourhood size) and C (subtracted constant) spinboxes.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Threshold'#
display_category: str = 'Segmentation'#

Region of interest#

ROIFilter crops each frame to a rectangular sub-region defined by a top-left corner (x, y) and dimensions (w, h). When the frame shape is first seen — or whenever it changes — the ROI parameters are clamped to fit within the frame. That check costs a single tuple comparison per frame; the clamp itself runs only on shape changes. The companion widget provides four spinboxes for x, y, w, and h, with w and h stepping in multiples of 8 for codec compatibility. Supports pipeline export.

ROI crop filter and companion Qt widget.

class QVideo.filters.roi.ROIFilter(x=0, y=0, w=128, h=128)[source]#

Bases: VideoFilter

Crop video frames to a rectangular region of interest.

The ROI is defined by its top-left corner (x, y) and its (w, h) dimensions. When the frame shape is first seen — or whenever it changes — the ROI is clamped to fit within the frame. That check costs a single tuple comparison per frame; the clamp itself runs only on shape changes.

Parameters:
  • x (int) – Column offset of the left edge of the ROI. Default: 0.

  • y (int) – Row offset of the top edge of the ROI. Default: 0.

  • w (int) – Width of the ROI in pixels. Default: 128.

  • h (int) – Height of the ROI in pixels. Default: 128.

add(image)[source]#

Incorporate a new frame into the filter state.

Parameters:

data (Image) – Input frame.

Return type:

None

to_code()[source]#

Return a FilterCode fragment for pipeline export.

Stateless filters implement this to enable exportPipeline(). Stateful filters (those that accumulate state across frames) return None to indicate they cannot be expressed as a single-frame pure function.

Return type:

FilterCode

Returns:

FilterCode or None – Code fragment, or None if export is not supported.

get()[source]#

Crop the current frame to the ROI bounds and return it.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]]

Returns:

Image – Cropped frame.

Raises:

RuntimeError – If called before the first add().

property x: int#

ROI x position.

property y: int#

ROI y position.

property w: int#

ROI width.

property h: int#

ROI height.

class QVideo.filters.roi.QROIFilter(parent=None)[source]#

Bases: QVideoFilter

Qt widget wrapper for ROIFilter.

display_name: str = 'Region of Interest'#
display_category: str = 'Preprocessing'#

Foreground estimation#

ForegroundEstimator uses OpenCV’s MOG2 Gaussian-mixture background subtractor to maintain a persistent background model B(x, y, t) and returns each frame divided by that background. For a multiplicative image model I = B × F the output approximates the foreground modulation F I / B. Unlike the median-based Normalize pipeline, MOG2 remains accurate even when foreground objects occupy a pixel for more than half the time, because the mixture tracks the most persistent Gaussian component rather than a simple median.

The output is scaled by a configurable mean (default 128) and cast to uint8, so that unmodulated pixels — where the frame equals the background — map to mean. Pixels where the foreground brightens the image map above mean; darker foreground maps below.

The companion QForegroundEstimator widget exposes two controls: history (number of frames integrated into the model) and threshold (the Mahalanobis-distance threshold used to classify a pixel as foreground). Changing either control resets the background model and triggers a fresh learning phase.

Foreground estimator using MOG2 Gaussian-mixture background model.

class QVideo.filters.foreground.ForegroundEstimator(history=500, varThreshold=16.0, mean=128.0)[source]#

Bases: AsyncVideoFilter

Foreground estimator using OpenCV MOG2 background subtraction.

Models each pixel as a Gaussian mixture over time to identify a persistent background, then returns each frame divided by that background. For a multiplicative image model I = B × F this recovers the foreground modulation F I / B.

The output is scaled by mean and cast to uint8 so that a pixel carrying no foreground modulation (I B) maps to mean. Pixels brighter than the background map above mean; darker pixels map below.

Parameters:
  • history (int) – Number of frames used to build the background model. Longer histories give a more stable estimate but adapt more slowly to illumination drift. Default: 500.

  • varThreshold (float) – Mahalanobis-distance threshold for classifying a pixel as foreground in the MOG2 model. Smaller values make the classifier more sensitive. Default: 16.0.

  • mean (float) – Output scale factor. A pixel where frame == background maps to this value in the output. Default: 128.0.

Notes

Changing history or varThreshold resets the background model, which discards accumulated statistics and triggers a re-learning phase.

property history: int#

Frames used to build the background model.

property varThreshold: float#

Mahalanobis-distance threshold for foreground classification.

property mean: float#

ratio == 1 maps to this pixel value.

Type:

Output scale factor

process(image)[source]#

Divide image by the MOG2 background estimate.

Called in the background thread.

Parameters:

image (Image) – Input frame (grayscale or BGR uint8).

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]]

Returns:

Image – Foreground-enhanced frame scaled to uint8.

class QVideo.filters.foreground.QForegroundEstimator(parent=None)[source]#

Bases: QVideoFilter

Widget for ForegroundEstimator with history and threshold spinboxes.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Foreground'#
display_category: str = 'Background'#

Circle transform#

CircleTransformFilter computes the orientation alignment transform (OAT) of Krishnatreya & Grier [KG14], which detects circularly symmetric ring-like features. At each pixel the gradient orientation is compared against the orientation expected for a ring centred at every candidate position; summing this evidence over all ring radii simultaneously produces a detection map whose peaks locate ring centres. Because the transform integrates over all radii, no radius parameter is required.

The gradient field is estimated by Savitzky-Golay differentiation [SG64], controlled by window (filter width in pixels, must be odd and ≥ 3) and polyorder (polynomial order, must be ≥ 1 and less than window). A larger window reduces noise but broadens detected peaks. The output is normalised per-frame to [0, 255] and returned as uint8; bright peaks indicate ring centres.

Computation runs in a background thread via AsyncVideoFilter, keeping the GUI responsive even for large frames. The companion QCircleTransformFilter widget exposes a window spinbox.

[KG14]

B.J. Krishnatreya and D.G. Grier, ‘Fast feature identification for holographic tracking: the orientation alignment transform,’ Optics Express 22, 12773–12778 (2014).

[SG64]

A. Savitzky and M.J.E. Golay, ‘Smoothing and differentiation of data by simplified least squares procedures,’ Analytical Chemistry 36, 1627–1639 (1964).

Orientation alignment transform filter — detects ring-like features.

class QVideo.filters.circletransform.CircleTransformFilter(window=13, polyorder=3)[source]#

Bases: AsyncVideoFilter

Orientation alignment transform (OAT) ring-detection filter.

Detects circularly symmetric ring-like features by computing the orientation alignment transform of Krishnatreya & Grier (2014). Each pixel’s gradient orientation is compared against the expected orientation for a ring centred at every candidate position; the result is a detection map whose peaks locate ring centres.

The transform integrates evidence from all ring radii simultaneously, so no radius parameter is required. Computation runs in a background thread via AsyncVideoFilter.

Parameters:
  • window (int) – Savitzky-Golay derivative window size [pixels]. Must be odd and greater than polyorder. Larger values smooth noise but reduce spatial resolution of detected ring centres. Default: 13.

  • polyorder (int) – Savitzky-Golay polynomial order. Must be less than window. Default: 3.

Notes

The OAT kernel \(K(\mathbf{k}) = e^{-2i\theta_k}/|\mathbf{k}|\) is cached by frame shape and recomputed only when the shape changes.

The output is normalised per-frame to [0, 255] and returned as uint8. Peak brightness indicates likely ring centres.

References

B. J. Krishnatreya and D. G. Grier, ‘Fast feature identification for holographic tracking: the orientation alignment transform,’ Optics Express 22, 12773–12778 (2014).

property window: int#

Savitzky-Golay derivative window [pixels], always odd and ≥ 3.

property polyorder: int#

Savitzky-Golay polynomial order, always ≥ 1.

process(image)[source]#

Compute the OAT of image and return a uint8 heat map.

Called in the background thread. Converts colour input to float grayscale, computes orientational order gradients via Savitzky-Golay differentiation, then convolves with the OAT kernel in Fourier space.

Parameters:

image (Image) – Input frame (grayscale or colour uint8).

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]]

Returns:

Image – OAT heat map, same spatial shape as image, dtype uint8. Bright peaks indicate ring centres.

class QVideo.filters.circletransform.QCircleTransformFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for CircleTransformFilter with a window spinbox.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Circle Transform'#
display_category: str = 'Feature Detection'#

Blob coloring#

BlobFilter runs OpenCV’s connected- component labeling on a binary (thresholded) frame and assigns each blob a distinct pseudo-color, making it easy to count and track individual objects visually.

Blob-coloring filter using connected-component labeling.

class QVideo.filters.blob.BlobFilter[source]#

Bases: AsyncVideoFilter

Blob-coloring filter.

Labels connected foreground regions in a binary frame and renders each blob in a distinct hue using OpenCV’s HSV color space. The labeling runs in a background thread so that large frames do not stall the GUI.

Notes

The input frame is expected to be a binary (uint8) image where non-zero pixels form the foreground. cv2.connectedComponents() assigns an integer label to each connected region; label 0 is background.

Labels are mapped linearly to the hue channel (0–179 in OpenCV) and merged with a full-saturation, full-value channel to produce an HSV image that is then converted to BGR. Background pixels (label 0) are forced to black after the color conversion.

The returned frame is always three-channel BGR uint8, with the same spatial dimensions as the input. If the input contains no foreground pixels a black BGR frame is returned.

process(image)[source]#

Label connected components and render each blob in a distinct hue.

Parameters:

image (Image) – Binary (uint8) input frame.

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]]

Returns:

Image – BGR image with each connected foreground region rendered in a distinct hue. Background pixels are black.

class QVideo.filters.blob.QBlobFilter(parent=None)[source]#

Bases: QVideoFilter

Widget wrapper for BlobFilter.

Displays the filter as a checkable group box. No adjustable parameters are exposed; checking the box enables the filter.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Blob'#
display_category: str = 'Segmentation'#

Artistic effects#

Two non-photorealistic rendering filters provide artistic transformations of each frame. Both require color (BGR) input; grayscale frames are automatically promoted to BGR before processing.

Pencil SketchPencilSketchFilter applies cv2.pencilSketch, which combines an edge-aware smoothing pass with a hand-drawn shading model to simulate a pencil drawing. Three parameters control the appearance:

  • σ_s (spatial sigma, 1–200) — controls how large a neighbourhood is smoothed together; larger values give bolder strokes.

  • σ_r (range sigma, 0–1) — controls how much tonal variation is absorbed into a single smooth region; smaller values preserve more texture.

  • shade (0–0.1) — overall darkness of the pencil strokes.

The output can be the three-channel color sketch (default) or the single-channel grayscale version, toggled via the Gray checkbox. Supports pipeline export.

CartoonCartoonFilter applies cv2.stylization, which flattens low-contrast regions while sharpening edges to produce a watercolor/cartoon look. σ_s and σ_r carry the same meanings as above. Supports pipeline export.

Note

Both filters use OpenCV’s domain-transform algorithm, which has O(N) pixel complexity but a relatively high constant. For large frames (≥ 1080p) the per-frame cost may be tens of milliseconds; the live-view frame rate will drop accordingly while either filter is active.

Artistic non-photorealistic filters and companion Qt widgets.

class QVideo.filters.artistic.PencilSketchFilter(sigma_s=60.0, sigma_r=0.07, shade_factor=0.05, gray=False)[source]#

Bases: AsyncVideoFilter

Pencil-drawing effect via OpenCV non-photorealistic rendering.

Applies cv2.pencilSketch in a background thread to produce a hand-drawn pencil look without blocking the GUI. Grayscale input is promoted to BGR before processing.

Parameters:
  • sigma_s (float) – Spatial extent of the filter in pixels. Range 1–200. Default: 60.0.

  • sigma_r (float) – How much color variation is treated as part of the same region. Range 0–1. Default: 0.07.

  • shade_factor (float) – Darkness of pencil strokes. Range 0–0.1. Default: 0.05.

  • gray (bool) – If True, return the single-channel grayscale sketch. If False, return the three-channel color sketch. Default: False.

process(image)[source]#

Apply the pencil-sketch transform in the background thread.

Parameters:

image (Image) – Input frame (grayscale or BGR uint8).

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]]

Returns:

Image – uint8 pencil-sketch frame.

to_code()[source]#

Return a FilterCode fragment for pipeline export.

Stateless filters implement this to enable exportPipeline(). Stateful filters (those that accumulate state across frames) return None to indicate they cannot be expressed as a single-frame pure function.

Return type:

FilterCode

Returns:

FilterCode or None – Code fragment, or None if export is not supported.

class QVideo.filters.artistic.QPencilSketchFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for PencilSketchFilter with parameter spinboxes.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Pencil Sketch'#
display_category: str = 'Artistic'#
class QVideo.filters.artistic.CartoonFilter(sigma_s=150.0, sigma_r=0.45)[source]#

Bases: AsyncVideoFilter

Cartoon/painterly stylization via OpenCV non-photorealistic rendering.

Applies cv2.stylization in a background thread, smoothing low-contrast regions while preserving edges to produce a watercolor/cartoon look. Grayscale input is promoted to BGR before processing.

Parameters:
  • sigma_s (float) – Spatial extent of the filter in pixels. Range 1–200. Default: 150.0.

  • sigma_r (float) – How much color variation is treated as part of the same region. Range 0–1. Default: 0.45.

process(image)[source]#

Apply cartoon stylization in the background thread.

Parameters:

image (Image) – Input frame (grayscale or BGR uint8).

Return type:

ndarray[tuple[Any, ...], dtype[ubyte]]

Returns:

Image – uint8 BGR stylized frame.

to_code()[source]#

Return a FilterCode fragment for pipeline export.

Stateless filters implement this to enable exportPipeline(). Stateful filters (those that accumulate state across frames) return None to indicate they cannot be expressed as a single-frame pure function.

Return type:

FilterCode

Returns:

FilterCode or None – Code fragment, or None if export is not supported.

class QVideo.filters.artistic.QCartoonFilter(parent=None)[source]#

Bases: QVideoFilter

Widget for CartoonFilter with sigma spinboxes.

Parameters:

parent (QtWidgets.QWidget or None) – Parent widget.

display_name: str = 'Cartoon'#
display_category: str = 'Artistic'#