Skip to content

capture

capture #

Procedures that capture data from device hardware.

Procedures that interact with device hardware to capture data from cameras, sensors, and other device capabilities. All capture procedures require user interaction and pause workflow execution until the user completes the action.

Example
import capturegraph as cg


class Session(cg.Struct):
    photo: cg.Image
    location: cg.Location


class FieldData(cg.Struct):
    sessions: cg.Map[cg.Date, Session]


@cg.procedure(FieldData)
def field_capture(root: cg.Procedure[cg.Path[FieldData]]):
    session = root.sessions[cg.CaptureTime()]
    session.photo &= cg.CaptureImage(label="Site Photo")
    session.location &= cg.CaptureLocation()

CaptureAlignedImage #

Bases: Procedure[Image]

Capture an image aligned to a reference image for consistent positioning.

Used for timelapse photography or when you need multiple images taken from the same perspective. The app guides the user to align their camera with the reference image before allowing capture.

Attributes:

Name Type Description
reference_image Input[Image]

The image to align against.

encoding Input[ImageEncoding]

How the photo is stored (default: ImageEncoding.HEIC) — see ImageEncoding for the HEIC/RAW trade-off.

alignment Input[ReferenceAlignment]

Whether alignment to the reference is mandatory (default: ReferenceAlignment.REQUIRED).

exposure_matching Input[ExposureMatching]

Whether the reference image's exposure (shutter + ISO, from its EXIF) is applied to the aligned shot so brightness matches (default: ExposureMatching.AUTO).

Example
# The reference is cached once (|=); later sessions align to it.
root.reference |= cg.CaptureImage(label="Reference Photo")
session.aligned &= cg.CaptureAlignedImage(
    label="Aligned Photo",
    reference_image=root.reference,
    encoding=cg.ImageEncoding.RAW,
)
Source code in capturegraph-lib/capturegraph/procedures/nodes/collection/capture.py
@make_procedure
class CaptureAlignedImage(Procedure[Image]):
    """Capture an image aligned to a reference image for consistent positioning.

    Used for timelapse photography or when you need multiple images taken from
    the same perspective. The app guides the user to align their camera with
    the reference image before allowing capture.

    Attributes:
        reference_image: The image to align against.
        encoding: How the photo is stored (default: ``ImageEncoding.HEIC``) —
            see ``ImageEncoding`` for the HEIC/RAW trade-off.
        alignment: Whether alignment to the reference is mandatory
            (default: ``ReferenceAlignment.REQUIRED``).
        exposure_matching: Whether the reference image's exposure (shutter +
            ISO, from its EXIF) is applied to the aligned shot so brightness
            matches (default: ``ExposureMatching.AUTO``).

    Example:
        ```python
        # The reference is cached once (|=); later sessions align to it.
        root.reference |= cg.CaptureImage(label="Reference Photo")
        session.aligned &= cg.CaptureAlignedImage(
            label="Aligned Photo",
            reference_image=root.reference,
            encoding=cg.ImageEncoding.RAW,
        )
        ```
    """

    reference_image: Input[Image]
    encoding: Input[ImageEncoding] = ImageEncoding.HEIC
    alignment: Input[ReferenceAlignment] = ReferenceAlignment.REQUIRED
    exposure_matching: Input[ExposureMatching] = ExposureMatching.AUTO

CaptureConstantColorImage #

Bases: Procedure[Image]

Capture an image using Apple's iOS 18 Constant Color API.

Uses flash with constant color correction to capture an image with consistent color temperature, removing the influence of ambient lighting. Useful for material scanning, product photography, and situations requiring accurate color. Requires iOS 18+ and a device with flash support.

Attributes:

Name Type Description
encoding Input[ImageEncoding]

How the photo is stored (default: ImageEncoding.HEIC) — see ImageEncoding for the HEIC/RAW trade-off.

Example
session.constant_color &= cg.CaptureConstantColorImage(label="Constant Color Capture")
Source code in capturegraph-lib/capturegraph/procedures/nodes/collection/capture.py
@make_procedure
class CaptureConstantColorImage(Procedure[Image]):
    """Capture an image using Apple's iOS 18 Constant Color API.

    Uses flash with constant color correction to capture an image with consistent
    color temperature, removing the influence of ambient lighting. Useful for
    material scanning, product photography, and situations requiring accurate color.
    Requires iOS 18+ and a device with flash support.

    Attributes:
        encoding: How the photo is stored (default: ``ImageEncoding.HEIC``) —
            see ``ImageEncoding`` for the HEIC/RAW trade-off.

    Example:
        ```python
        session.constant_color &= cg.CaptureConstantColorImage(label="Constant Color Capture")
        ```
    """

    encoding: Input[ImageEncoding] = ImageEncoding.HEIC

CaptureFlashNoFlash #

Bases: Procedure[FlashPair]

Capture a pair of images: one with flash and one without.

This capture mode is useful for computational photography applications that need to separate flash illumination from ambient lighting. The result is a bundle containing two named images: 'flash' and 'no_flash'.

Attributes:

Name Type Description
encoding Input[ImageEncoding]

How the photos are stored (default: ImageEncoding.HEIC) — see ImageEncoding for the HEIC/RAW trade-off.

Example
# Capture a flash/no-flash pair for material analysis
session.flash_pair &= cg.CaptureFlashNoFlash(label="Flash Pair Capture")
Source code in capturegraph-lib/capturegraph/procedures/nodes/collection/capture.py
@make_procedure
class CaptureFlashNoFlash(Procedure[FlashPair]):
    """Capture a pair of images: one with flash and one without.

    This capture mode is useful for computational photography applications that
    need to separate flash illumination from ambient lighting. The result is a
    bundle containing two named images: 'flash' and 'no_flash'.

    Attributes:
        encoding: How the photos are stored (default: ``ImageEncoding.HEIC``) —
            see ``ImageEncoding`` for the HEIC/RAW trade-off.

    Example:
        ```python
        # Capture a flash/no-flash pair for material analysis
        session.flash_pair &= cg.CaptureFlashNoFlash(label="Flash Pair Capture")
        ```
    """

    encoding: Input[ImageEncoding] = ImageEncoding.HEIC

CaptureImage #

Bases: Procedure[Image]

Capture a single image using the device camera.

The most basic image capture procedure that prompts the user to take a photo. The captured image can then be saved, processed, or used as input to other procedures.

Attributes:

Name Type Description
encoding Input[ImageEncoding]

How the photo is stored (default: ImageEncoding.HEIC) — see ImageEncoding for the HEIC/RAW trade-off.

Example
# Simple photo capture
session.photo &= cg.CaptureImage(label="Take Photo")

# Encoding driven by a cached user preference
root.encoding |= cg.UserInputChoice(output_type=cg.ImageEncoding, label="Encoding")
session.photo &= cg.CaptureImage(label="Photo", encoding=root.encoding)
Source code in capturegraph-lib/capturegraph/procedures/nodes/collection/capture.py
@make_procedure
class CaptureImage(Procedure[Image]):
    """Capture a single image using the device camera.

    The most basic image capture procedure that prompts the user to take a photo.
    The captured image can then be saved, processed, or used as input to other
    procedures.

    Attributes:
        encoding: How the photo is stored (default: ``ImageEncoding.HEIC``) —
            see ``ImageEncoding`` for the HEIC/RAW trade-off.

    Example:
        ```python
        # Simple photo capture
        session.photo &= cg.CaptureImage(label="Take Photo")

        # Encoding driven by a cached user preference
        root.encoding |= cg.UserInputChoice(output_type=cg.ImageEncoding, label="Encoding")
        session.photo &= cg.CaptureImage(label="Photo", encoding=root.encoding)
        ```
    """

    encoding: Input[ImageEncoding] = ImageEncoding.HEIC

CaptureImageSequence #

Bases: Procedure[Array[Image]]

Capture multiple images in sequence as a bundle.

Prompts the user to capture several related images that will be grouped together. Useful for creating image series, documenting multiple angles, or collecting related visual data.

Attributes:

Name Type Description
encoding Input[ImageEncoding]

How the photos are stored (default: ImageEncoding.HEIC) — see ImageEncoding for the HEIC/RAW trade-off.

Example
# Capture multiple angles of a specimen
session.specimen_photos &= cg.CaptureImageSequence(label="All Angles")
Source code in capturegraph-lib/capturegraph/procedures/nodes/collection/capture.py
@make_procedure
class CaptureImageSequence(Procedure[Array[Image]]):
    """Capture multiple images in sequence as a bundle.

    Prompts the user to capture several related images that will be grouped
    together. Useful for creating image series, documenting multiple angles,
    or collecting related visual data.

    Attributes:
        encoding: How the photos are stored (default: ``ImageEncoding.HEIC``) —
            see ``ImageEncoding`` for the HEIC/RAW trade-off.

    Example:
        ```python
        # Capture multiple angles of a specimen
        session.specimen_photos &= cg.CaptureImageSequence(label="All Angles")
        ```
    """

    encoding: Input[ImageEncoding] = ImageEncoding.HEIC

CaptureImagesByLabel #

Bases: Procedure[Map[String, Array[Image]]]

Capture one image sequence per label, returning a map from label to sequence.

Each label becomes its own capture button; the user collects any number of images under each. The result is a Map[String, Array[Image]] keyed by the labels — index it to use one label's sequence (photos["Front"], a MapKey), or cache the whole map into a Map[String, …] slot. A key that is not one of the labels produces no value, so its cache stores nothing.

Attributes:

Name Type Description
labels Setting[list[str]]

The capture buttons, one per string (order preserved). The keys of the returned map.

encoding Input[ImageEncoding]

How the photos are stored (default: ImageEncoding.HEIC) — see ImageEncoding for the HEIC/RAW trade-off.

Example
photos = cg.CaptureImagesByLabel(
    label="Specimen",
    labels=["Front", "Side", "Back"],
)
session.front &= photos["Front"]  # one label's Array[Image]
session.views &= photos  # the whole Map[String, ImageSequence]
Source code in capturegraph-lib/capturegraph/procedures/nodes/collection/capture.py
@make_procedure
class CaptureImagesByLabel(Procedure[Map[String, Array[Image]]]):
    """Capture one image sequence per label, returning a map from label to sequence.

    Each label becomes its own capture button; the user collects any number of
    images under each. The result is a ``Map[String, Array[Image]]`` keyed by the
    labels — index it to use one label's sequence (``photos["Front"]``, a
    ``MapKey``), or cache the whole map into a ``Map[String, …]`` slot. A key that
    is not one of the labels produces no value, so its cache stores nothing.

    Attributes:
        labels: The capture buttons, one per string (order preserved). The keys of
            the returned map.
        encoding: How the photos are stored (default: ``ImageEncoding.HEIC``) —
            see ``ImageEncoding`` for the HEIC/RAW trade-off.

    Example:
        ```python
        photos = cg.CaptureImagesByLabel(
            label="Specimen",
            labels=["Front", "Side", "Back"],
        )
        session.front &= photos["Front"]  # one label's Array[Image]
        session.views &= photos  # the whole Map[String, ImageSequence]
        ```
    """

    labels: Setting[list[str]]
    encoding: Input[ImageEncoding] = ImageEncoding.HEIC

    def static_map_keys(self) -> frozenset[str]:
        """The labels, known at authoring time since they are a fixed setting."""
        return frozenset(self.labels)

static_map_keys() #

The labels, known at authoring time since they are a fixed setting.

Source code in capturegraph-lib/capturegraph/procedures/nodes/collection/capture.py
def static_map_keys(self) -> frozenset[str]:
    """The labels, known at authoring time since they are a fixed setting."""
    return frozenset(self.labels)

CaptureLocation #

Bases: Procedure[Location]

Capture the current GPS location of the device.

Records the device's current latitude, longitude, altitude, and other location metadata. Useful for geotagging data collection or tracking where measurements were taken.

Source code in capturegraph-lib/capturegraph/procedures/nodes/collection/capture.py
@make_procedure
class CaptureLocation(Procedure[Location]):
    """Capture the current GPS location of the device.

    Records the device's current latitude, longitude, altitude, and other
    location metadata. Useful for geotagging data collection or tracking
    where measurements were taken.
    """

CapturePanorama #

Bases: Procedure[ImagePanorama]

Capture a panorama as a sequence of oriented photos.

Photosynth-style capture: the user rotates the device about the camera's optical center while photos are placed on a sphere using the gyroscope. Photos fire automatically when the viewfinder reaches uncovered area (with a manual mode available). The result bundles each image with the device orientation at capture, plus an equirectangular preview composite.

Attributes:

Name Type Description
encoding Input[ImageEncoding]

How the photos are stored (default: ImageEncoding.HEIC) — see ImageEncoding for the HEIC/RAW trade-off.

overlap_ratio Input[Number]

Fraction of the field of view shared between adjacent frames; higher values fire more, closer photos (default: 0.6).

Example
# Capture a RAW panorama of the site
session.site_panorama &= cg.CapturePanorama(
    label="Site Panorama",
    encoding=cg.ImageEncoding.RAW,
)
Source code in capturegraph-lib/capturegraph/procedures/nodes/collection/capture.py
@make_procedure
class CapturePanorama(Procedure[ImagePanorama]):
    """Capture a panorama as a sequence of oriented photos.

    Photosynth-style capture: the user rotates the device about the camera's
    optical center while photos are placed on a sphere using the gyroscope.
    Photos fire automatically when the viewfinder reaches uncovered area (with
    a manual mode available). The result bundles each image with the device
    orientation at capture, plus an equirectangular preview composite.

    Attributes:
        encoding: How the photos are stored (default: ``ImageEncoding.HEIC``) —
            see ``ImageEncoding`` for the HEIC/RAW trade-off.
        overlap_ratio: Fraction of the field of view shared between adjacent
            frames; higher values fire more, closer photos (default: 0.6).

    Example:
        ```python
        # Capture a RAW panorama of the site
        session.site_panorama &= cg.CapturePanorama(
            label="Site Panorama",
            encoding=cg.ImageEncoding.RAW,
        )
        ```
    """

    encoding: Input[ImageEncoding] = ImageEncoding.HEIC
    overlap_ratio: Input[Number] = 0.6

CaptureTime #

Bases: Procedure[Time]

Capture the current timestamp when the procedure executes.

Records the exact date and time when this procedure is executed, which can be useful for timestamping data collection or measuring time intervals between procedures.

Source code in capturegraph-lib/capturegraph/procedures/nodes/collection/capture.py
@make_procedure
class CaptureTime(Procedure[Time]):
    """Capture the current timestamp when the procedure executes.

    Records the exact date and time when this procedure is executed,
    which can be useful for timestamping data collection or measuring
    time intervals between procedures.
    """

CaptureVideo #

Bases: Procedure[Video]

Capture a video using the device camera.

Prompts the user to record a video. The recorded video can then be saved or used as input to other procedures.

Attributes:

Name Type Description
dynamic_range Input[DynamicRange]

Whether the clip records SDR or 10-bit HDR (default: DynamicRange.SDR) — best-effort, see DynamicRange.

format Input[VideoFormat]

The frame-rate floor / resolution priority (default: VideoFormat.RESOLUTION) — see VideoFormat for the exact semantics of each case. VideoFormat.SLOW_MOTION makes this the slow-motion capture: the device's best high-speed tier (240 fps, else 120 fps), at whatever resolution that tier offers.

exposure_lock Input[ExposureLock]

Whether exposure and white balance freeze for the whole clip (default: ExposureLock.AUTO) — see ExposureLock; the ARKit posed captures lock unconditionally.

Note

The default dynamic_range is a single Constant node created at class definition — every instance that omits the field shares that one node (one UUID) in the serialized graph.

Example
# Simple video capture
session.video &= cg.CaptureVideo(label="Record Video")

# HDR video capture
session.video &= cg.CaptureVideo(label="HDR Video", dynamic_range=cg.DynamicRange.HDR)

# Slow-motion capture
session.video &= cg.CaptureVideo(label="Slow-Mo", format=cg.VideoFormat.SLOW_MOTION)

# Lock exposure and white balance for a photometrically stable clip
session.video &= cg.CaptureVideo(label="Locked Video", exposure_lock=cg.ExposureLock.LOCKED)
Source code in capturegraph-lib/capturegraph/procedures/nodes/collection/capture.py
@make_procedure
class CaptureVideo(Procedure[Video]):
    """Capture a video using the device camera.

    Prompts the user to record a video. The recorded video can then be saved
    or used as input to other procedures.

    Attributes:
        dynamic_range: Whether the clip records SDR or 10-bit HDR
            (default: ``DynamicRange.SDR``) — best-effort, see ``DynamicRange``.
        format: The frame-rate floor / resolution priority (default:
            ``VideoFormat.RESOLUTION``) — see ``VideoFormat`` for the
            exact semantics of each case. ``VideoFormat.SLOW_MOTION`` makes
            this the slow-motion capture: the device's best high-speed tier
            (240 fps, else 120 fps), at whatever resolution that tier offers.
        exposure_lock: Whether exposure and white balance freeze for the
            whole clip (default: ``ExposureLock.AUTO``) — see ``ExposureLock``;
            the ARKit posed captures lock unconditionally.

    Note:
        The default ``dynamic_range`` is a single ``Constant`` node created at
        class definition — every instance that omits the field shares that one
        node (one UUID) in the serialized graph.

    Example:
        ```python
        # Simple video capture
        session.video &= cg.CaptureVideo(label="Record Video")

        # HDR video capture
        session.video &= cg.CaptureVideo(label="HDR Video", dynamic_range=cg.DynamicRange.HDR)

        # Slow-motion capture
        session.video &= cg.CaptureVideo(label="Slow-Mo", format=cg.VideoFormat.SLOW_MOTION)

        # Lock exposure and white balance for a photometrically stable clip
        session.video &= cg.CaptureVideo(label="Locked Video", exposure_lock=cg.ExposureLock.LOCKED)
        ```
    """

    dynamic_range: Input[DynamicRange] = DynamicRange.SDR
    format: Input[VideoFormat] = VideoFormat.RESOLUTION
    exposure_lock: Input[ExposureLock] = ExposureLock.AUTO

CaptureWeather #

Bases: Procedure[Weather]

Capture current weather conditions at a location.

Retrieves weather information such as temperature, humidity, atmospheric pressure, and conditions. Useful for environmental data collection and context.

Attributes:

Name Type Description
location Input[Location]

Location to fetch weather for. Defaults to a CaptureLocation so the input is always present and resolves to the device's current location when the author does not supply one.

Source code in capturegraph-lib/capturegraph/procedures/nodes/collection/capture.py
@make_procedure
class CaptureWeather(Procedure[Weather]):
    """Capture current weather conditions at a location.

    Retrieves weather information such as temperature, humidity,
    atmospheric pressure, and conditions. Useful for environmental
    data collection and context.

    Attributes:
        location: Location to fetch weather for. Defaults to a ``CaptureLocation``
            so the input is always present and resolves to the device's current
            location when the author does not supply one.
    """

    location: Input[Location] = field(
        default_factory=lambda: CaptureLocation(),
    )