visual-cortex 0.2.1

Watch screen regions and receive typed events over async streams when patterns match: OCR, template matching, and pixel conditions on live captures.
docs.rs failed to build visual-cortex-0.2.1
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build: visual-cortex-0.2.0

Watch screen regions and receive typed events over async streams when patterns match — OCR, template matching, and pixel conditions on live captures.

Concepts

  • A [Session] owns one capture stream (a real display/window via [Target], or a scripted [FakeSource] for headless use). Each new frame lands in a latest-frame slot — newest wins, stale frames drop.

  • A watcher ([Session::watch]) evaluates one [Region] at its own [Rate]: cheap gates run first (an implicit pixels-changed gate, plus any you add), then the main [Detector].

  • Emission modes decide when detector output becomes an [Event]:

    builder call fires
    default / .on_change() [EventKind::Changed] on output transitions
    .on_threshold(pred) [EventKind::ThresholdCrossed] when the predicate flips
    .template(png, thr) [EventKind::TemplateAppeared] / TemplateVanished
    .on_every_match() [EventKind::Matched] every matching tick
  • Heavy detectors (OCR — anything with [Detector::is_heavy]) run on the blocking thread pool; the async scheduler never stalls on inference.

Quickstart (headless)

use visual_cortex::{Brightness, EventKind, FakeSource, Frame, Rate, Region, Session};

# fn main() -> visual_cortex::Result<()> {
let rt = tokio::runtime::Runtime::new().expect("tokio runtime");
rt.block_on(async {
    let session = Session::builder()
        .source(FakeSource::new([Frame::solid(64, 64, [200, 200, 200, 255])]))
        .build()
        .await?;

    let mut events = session
        .watch("bright")
        .region(Region::Full)
        .rate(Rate::hz(50.0))
        .detector(Brightness)
        .subscribe()?;

    let ev = events.next().await.expect("stream open");
    assert!(matches!(ev.kind, EventKind::Changed { .. }));
    Ok(())
})
# }

Real capture (macOS): swap the source for .target(Target::display(0)). OCR: add the visual-cortex-ocr-onnx crate and use .ocr_text(PaddleOcr::new().await.map_err(Error::engine)?). See the guide for the full walk-through.

macOS permissions

Real capture needs the Screen Recording permission, granted to the process that runs your binary (your terminal/IDE). The first request after a fresh grant may still report PermissionDenied — macOS applies the grant per process launch, so re-run once after granting.