Skip to content

Segment Image Using Adaptive Threshold

SUMMARY

Segment Image Using Adaptive Threshold segments an image by recomputing a threshold for every pixel from its own local neighborhood.

Rather than comparing every pixel against one fixed, image-wide threshold, this method looks at each pixel's block_size x block_size neighborhood and computes a local mean, or a Gaussian-weighted local mean, minus an offset_constant, then compares the pixel against that local value via threshold_type. Because each region of the image gets its own threshold, this copes far better with uneven lighting — a shadow or lighting gradient — than a single global threshold. Compare with segment_image_using_local_threshold for a simpler local-thresholding option with fewer knobs.

Use this Skill when you want to segment images under uneven lighting, shadows, or lighting gradients using a per-pixel adaptive threshold with control over the averaging method and comparison direction.

The Skill

python
from telekinesis import cornea

segmented_image = cornea.segment_image_using_adaptive_threshold(
    image=image,
    max_value=255,
    adaptive_method="gaussian constant",
    threshold_type="binary",
    block_size=61,
    offset_constant=5,
)
API Reference
Full parameter and return type documentation for segment_image_using_adaptive_threshold.
View Reference →

Example

Input Image

Input image

Original image with non-uniform lighting

Output Image

Output image

Segmented image using adaptive threshold - handles non-uniform lighting

The Code

python
"""
Demonstrates adaptive threshold segmentation.
"""

from loguru import logger
import rerun as rr

from telekinesis import cornea, datatypes

def segment_image_using_adaptive_threshold_example():
    """Applies adaptive thresholding to segment the image."""
    # ===================== Load Image ==========================================
    image_url = "https://assets.telekinesis.ai/examples/v1/images/car_number_plate.jpg"
    image = datatypes.Image.from_url(url=image_url)

    # ===================== Run Skill ==========================================
    segmented_image = cornea.segment_image_using_adaptive_threshold(
        image=image, max_value=255, adaptive_method="gaussian constant",
        threshold_type="binary", block_size=61, offset_constant=5
    )

    # ===================== Log ================================================
    logger.success(f"Segmented {image} using adaptive thresholding.")
    logger.success(f"Results: {segmented_image}")
    logger.info(f"Segmented image label codes: {segmented_image.label_codes}")
    logger.info(f"Segmented image number of labels: {segmented_image.number_of_labels}")
    logger.info(f"Segmented image shape: {segmented_image.shape}")
    logger.info(f"Segmented image dtype: {segmented_image.dtype}")

    # ===================== Visualization  (Optional) ======================
    rr.init("segment_image_using_adaptive_threshold_example", spawn=True)
    datatypes.visualize(image, entity_path="/input_image")
    datatypes.visualize(segmented_image, entity_path="/segmented_image")


if __name__ == "__main__":
    segment_image_using_adaptive_threshold_example()

Runnable examples are available in the Telekinesis examples repository.

Follow the README in that repository to set up the environment, run this specific example with:

bash
cd telekinesis-examples
python examples/segmentation/segment_image_using_adaptive_threshold.py

Parameter Configuration

KeyTypeDefaultDescription
imagedatatypes.Image | np.ndarrayrequiredInput image to segment, shape (H, W) or (H, W, 3)
max_valuedatatypes.Int | int255Value assigned to pixels that pass the threshold test (see threshold_type)
adaptive_methoddatatypes.String | str"gaussian constant"How each pixel's local threshold is computed from its block_size x block_size neighborhood. Literal options: "mean constant", "gaussian constant"
threshold_typedatatypes.String | str"binary"How a pixel's value is compared against its local threshold. Literal options: "binary", "binary_inv"
block_sizedatatypes.Int | int11Size, in pixels, of the square neighborhood used to compute each pixel's local threshold. Expected to be an odd value greater than 1
offset_constantdatatypes.Int | int2Constant subtracted from the computed local mean (or Gaussian-weighted mean) before comparison

Returns

TypeDescription
datatypes.SegmentationImageA per-pixel label map, shape (H, W), reflecting the local threshold comparison above. Use .data for the raw label array, .label_codes for the sorted array of unique ids present, .number_of_labels for how many distinct labels were found, and .shape/.dtype for its size and label dtype.

Raises

ExceptionCondition
TypeErrorA parameter's value does not match its expected type (see the Parameter Configuration table above)
ConfigurationErrorThe TELEKINESIS_API_KEY environment variable is not set
SerializationErrorThe request input failed to serialize, or the response failed to deserialize
RequestTimeoutErrorThe request to the Cornea service timed out
TransportErrorA network failure occurred before a response was received
ClientErrorThe Cornea service rejected the request due to invalid input, invalid data, or another unexpected 4xx response
AuthenticationErrorThe API key was rejected as invalid or expired
AuthenticationServiceErrorThe authentication service was unavailable
ServerErrorThe Cornea service returned a 5xx or otherwise unexpected error response

How to Tune the Parameters

The segment_image_using_adaptive_threshold Skill exposes five parameters, extending segment_image_using_local_threshold's single block_size knob with control over the local-averaging method, the comparison direction, and the output values.

max_value

  • Controls: The value written into the output for pixels that pass the threshold_type test.
  • Units: Pixel intensity (typically 0–255 for 8-bit images)
  • Default: 255
  • Increase → raises the value assigned to passing pixels
  • Decrease → lowers the value assigned to passing pixels
  • Typical range: 255, matching the default used by the SDK example

adaptive_method

  • Controls: How each pixel's local threshold is computed from its block_size x block_size neighborhood.
  • Default: "gaussian constant"
    • Options:
      • "mean constant" — threshold = (neighborhood mean) − offset_constant
      • "gaussian constant" (default) — threshold = (Gaussian-weighted neighborhood mean, giving nearby pixels more influence) − offset_constant; smoother and less noise-sensitive than the plain mean

threshold_type

  • Controls: How a pixel's value is compared against its local threshold.
  • Default: "binary"
    • Options:
      • "binary" (default) — pixels above the threshold become max_value, others become 0
      • "binary_inv" — the inverse: pixels above the threshold become 0, others become max_value. Use this when the region of interest is darker than its surroundings

block_size

  • Controls: The size of the square neighborhood used to compute each pixel's local threshold.
  • Units: Pixels (odd integer greater than 1)
  • Default: 11
  • Increase → smoother, more slowly-varying thresholds — better for larger, evenly-lit regions
  • Decrease → reacts to finer local lighting changes
  • Typical range: depends on image resolution and the scale of the lighting variation you want to cancel out; the SDK example uses 61

offset_constant

  • Controls: A constant subtracted from the computed local mean (or Gaussian-weighted mean) before comparison.
  • Units: Pixel intensity
  • Default: 2
  • Increase → stricter threshold — fewer pixels pass (useful for finer text or edge extraction)
  • Decrease → (or use a negative value) more permissive threshold — more pixels pass
  • Typical range: depends on contrast; the SDK example uses 5

TIP

Match threshold_type to which side of the threshold your region of interest is on: "binary" when it's brighter than its surroundings, "binary_inv" when it's darker. Set block_size large enough to span the lighting variation you want to cancel out, then use offset_constant to make the threshold more or less selective.

Where to Use the Skill

Common pipelines include:

  • Document and label imaging under shadows or lighting gradients – e.g. the SDK example's license-plate image, the exact case the docstring calls out as the motivation for local-neighborhood thresholding
  • Industrial inspection under uneven illumination – parts lit unevenly across a workspace, where the choice of averaging method affects noise sensitivity
  • Pipelines that need an inverted mask – using threshold_type="binary_inv" to isolate regions of interest that are darker than their surroundings

Alternative Skills

Skillvs. Segment Image Using Adaptive Threshold
segment_image_using_local_thresholdThe simpler of the two — only exposes block_size. Reach for local threshold first; switch to adaptive threshold when you need to choose the local-averaging method (adaptive_method) or an inverted comparison (threshold_type).
segment_image_using_thresholdA single, manually chosen global threshold — the simplest possible segmentation. Use it when you already know a good threshold value; use adaptive threshold when lighting varies across the image.
segment_image_using_otsu_thresholdAutomatically picks one global threshold from the image's intensity histogram — no parameters to tune. Use it for a clear bimodal histogram under uniform lighting; use adaptive threshold when lighting is uneven.
segment_image_using_yen_thresholdAnother automatic, parameter-free global threshold, based on an entropy criterion rather than Otsu's variance criterion. Use it for histograms with unequal-sized foreground/background regions under uniform lighting; use adaptive threshold when lighting is uneven.

When Not to Use the Skill

Do not use Segment Image Using Adaptive Threshold when:

  • Lighting is already uniform across the image – a single global threshold (segment_image_using_threshold, segment_image_using_otsu_threshold, or segment_image_using_yen_threshold) achieves the same result without a neighborhood size or offset to tune
  • You only need one knobsegment_image_using_local_threshold exposes just block_size and is simpler to configure when the extra control over averaging method and threshold direction isn't needed

TIP

segment_image_using_adaptive_threshold is the go-to method for images with shadows, gradients, or other non-uniform lighting conditions that would cause a global threshold to fail — reach for it once segment_image_using_local_threshold's single block_size knob isn't enough.