Skip to main content

What is Iris?

Iris is a stateless, high-performance face recognition API built in Rust, designed specifically for hospital IT systems to identify unresponsive patients in real-time. By comparing emergency captures against secure patient databases, Iris provides sub-100ms inference times while maintaining absolute privacy through zero-persistence architecture.
Iris is infrastructure, not storage. It returns mathematical similarity scores between images, allowing hospitals to link results to their own secure Electronic Medical Record (EMR) systems.

Key Use Cases

Iris excels in scenarios where rapid, privacy-conscious biometric identification is critical:

Emergency Patient Identification

Identify unconscious or unresponsive patients in emergency departments by comparing their face against the hospital’s patient database.

Medical Record Linking

Match patients to their correct medical records when traditional identification methods (ID cards, verbal confirmation) are unavailable.

Cross-Department Verification

Verify patient identity during transfers between departments, ensuring continuity of care and reducing medical errors.

Access Control Integration

Integrate with secure area access systems for authorized personnel or patient verification in restricted zones.

Core Architecture

Iris is built on three fundamental principles that make it suitable for healthcare environments:

1. Stateless Processing

Every image is processed entirely in volatile memory (RAM) and destroyed immediately after feature extraction. The workflow:
1

Image Download

Images are fetched from URLs or decoded from Base64 data URIs directly into RAM
// From main.rs:47-60
async fn download_and_decode(url: &str) -> Result<Mat> {
    let bytes: Vec<u8> = if url.starts_with("data:") {
        // Decode Base64 data URI
        let comma = url.find(',').ok_or_else(|| anyhow!("Invalid data URI"))?;
        general_purpose::STANDARD.decode(&url[comma + 1..])?;
    } else {
        // Download from URL
        let client = reqwest::Client::builder().user_agent("IrisAPI/1.0").build()?;
        let response = client.get(url).send().await?;
        response.bytes().await?.to_vec()
    };
    // Decode image directly into OpenCV Mat structure
    let vector_uint8 = core::Vector::<u8>::from_iter(bytes);
    let img = imgcodecs::imdecode(&vector_uint8, imgcodecs::IMREAD_COLOR)?;
    Ok(img)
}
2

Face Detection

YuNet model detects faces and extracts facial landmarks in the image
// From face.rs:26-28
det.set_input_size(img.size())?;
let mut faces = Mat::default();
det.detect(img, &mut faces)?;
3

Feature Extraction

SFace model generates a 128-dimensional feature vector representing the face
// From face.rs:30-36
if faces.rows() > 0 {
    let face_data = faces.row(0)?;
    let mut aligned = Mat::default();
    rec.align_crop(img, &face_data, &mut aligned)?;
    let mut feature = Mat::default();
    rec.feature(&aligned, &mut feature)?;
}
4

Similarity Comparison

Feature vectors are compared using cosine similarity, producing a match score
// From main.rs:103-109
if let Ok(Some(p_emb)) = get_embedding(&p_img, det, rec) {
    let score = rec.match_(&t_emb, &p_emb, 
        objdetect::FaceRecognizerSF_DisType::FR_COSINE as i32)?;
    if score > 0.363 {  // Threshold for positive match
        results.push(MatchResult { name: person.name, probability: score * 100.0 });
    }
}
5

Memory Cleanup

All image data and feature vectors are destroyed when they go out of scope—no persistence
Iris never writes biometric data to disk. All processing happens in RAM, and data is automatically cleaned up by Rust’s ownership system.

2. ONNX-Accelerated Models

Iris uses two pre-trained neural networks from OpenCV Zoo:
Model: face_detection_yunet_2023mar.onnxPurpose: Detects faces in images and extracts 5-point facial landmarks (eyes, nose, mouth corners)Performance: Processes 320×320 images with confidence threshold of 0.9Configuration:
// From face.rs:11-13
let detector = objdetect::FaceDetectorYN::create(
    "face_detection_yunet_2023mar.onnx", 
    "", 
    core::Size::new(320, 320),  // Input size
    0.9,   // Score threshold
    0.3,   // NMS threshold
    5000,  // Top K
    0, 0
)?;
Model: face_recognition_sface_2021dec.onnxPurpose: Generates 128-dimensional feature embeddings from aligned face cropsPerformance: Produces embeddings that enable sub-100ms comparison timesMatch Threshold: Cosine similarity score > 0.363 indicates a positive matchConfiguration:
// From face.rs:14-16
let recognizer = objdetect::FaceRecognizerSF::create(
    "face_recognition_sface_2021dec.onnx", 
    "", 
    0, 0
)?;

3. Rust Performance

Built with Rust for memory safety and performance:
  • Zero-cost abstractions: No runtime overhead for safety guarantees
  • Ownership system: Automatic memory cleanup without garbage collection
  • Async runtime: Tokio-powered concurrency for handling multiple requests
  • Type safety: Compile-time guarantees prevent common programming errors

API Design

Iris provides a minimal REST API with three endpoints:

POST /compare

Compare a target face against a list of people

GET /stats

Retrieve API usage statistics

GET /health

Check API health status

Request Flow

Here’s how a typical comparison request flows through the system:
The Face Engine uses a mutex to ensure thread-safe access to the ONNX models, processing one face at a time while maintaining high throughput.

Security & Privacy

Iris is designed with healthcare data privacy regulations in mind:

Zero Persistence

Images processed in RAM only—no disk writes, no logs, no retention

Rate Limiting

5 requests/second per IP with burst capacity of 10

CORS Enabled

Configurable CORS for secure frontend integration

No PII Storage

Returns only similarity scores—hospitals maintain their own EMR data

Match Threshold

The default threshold of 0.363 for cosine similarity is based on SFace model recommendations:
  • Score > 0.363: Positive match (same person)
  • Score ≤ 0.363: No match (different people)
// From main.rs:104
if score > 0.363 {
    results.push(MatchResult {
        name: person.name,
        probability: (score * 100.0).round(),
    });
}
In production, you may want to adjust this threshold based on your specific accuracy requirements and false positive tolerance.

Deployment Options

Iris can be deployed in multiple configurations:
  1. Local Development: Run directly with cargo run --release
  2. Docker Container: Deploy as a containerized service (see Dockerfile)
  3. Kubernetes: Scale horizontally with multiple replicas
  4. On-Premise: Install on hospital infrastructure for data sovereignty

Next Steps

Quickstart Guide

Get Iris running locally in 5 minutes

API Reference

Explore the complete API documentation

Architecture Deep Dive

Learn about Iris’s internal design

Docker Deployment

Deploy Iris in production environments

Build docs developers (and LLMs) love