Skip to content

Tripwire Plugin

Description

Tripwire is a line-crossing detection plugin for CVEDIA-RT that detects when objects cross virtual lines or boundaries in video scenes. It provides advanced crossing detection with directional analysis, tailgating detection, and configurable triggering conditions.

The Tripwire plugin implements sophisticated line-crossing analytics that can detect when tracked objects cross predefined virtual lines, with support for directional filtering, speed analysis, and complex crossing scenarios. It integrates seamlessly with tracking systems to provide accurate crossing events for security, traffic monitoring, and analytics applications.

Key Features

  • Virtual Line Definition: Create custom line segments with configurable properties
  • Directional Analysis: Bidirectional or unidirectional crossing detection
  • Multi-Point Lines: Support for complex multi-segment line configurations
  • Tailgating Detection: Detect multiple objects crossing in close succession
  • Crossing Validation: Track-based validation to reduce false positives
  • Speed Analysis: Calculate crossing speed and trajectory information
  • Event Generation: Generate structured crossing events with metadata
  • Group Management: Organize tripwires into logical groups for batch processing
  • Lua Integration: Full Lua scripting support for custom crossing logic
  • Bandwidth Control: Configurable sensitivity zones around tripwire lines

Requirements

Hardware Requirements

  • CPU: Multi-core processor for real-time line-crossing analysis
  • Memory: Minimum 2GB RAM for typical tripwire scenarios
  • Platform: All supported platforms (Windows, Linux, embedded)

Software Dependencies

  • CVEDIA-RT Core: Base plugin infrastructure and interfaces
  • Tracking System: Requires tracked objects with trajectories for accurate detection
  • Mathematical Libraries: Geometric computation and line intersection algorithms
  • Sol2: Lua scripting integration

Configuration

Basic Configuration

{
  "tripwires": [
    {
      "name": "entrance_line",
      "group": "security",
      "vertices": [
        {"x": 100, "y": 200},
        {"x": 300, "y": 200}
      ],
      "direction": "Both",
      "color": [1.0, 0.0, 0.0, 1.0],
      "bandwidth": 10.0,
      "min_crossing_time": 0.5
    }
  ]
}

Advanced Configuration

{
  "tripwires": [
    {
      "name": "perimeter_line",
      "group": "security",
      "vertices": [
        {"x": 50, "y": 150},
        {"x": 200, "y": 180},
        {"x": 350, "y": 160}
      ],
      "direction": "Up",
      "color": [1.0, 0.0, 0.0, 1.0],
      "bandwidth": 15.0,
      "min_crossing_time": 1.0,
      "max_crossing_time": 5.0,
      "tailgating_threshold": 2.0,
      "enabled": true,
      "sensitivity": 0.8
    },
    {
      "name": "exit_detector",
      "group": "traffic",
      "vertices": [
        {"x": 400, "y": 300},
        {"x": 600, "y": 320}
      ],
      "direction": "Down",
      "color": [0.0, 1.0, 0.0, 1.0],
      "bandwidth": 12.0,
      "min_track_hits": 3,
      "speed_analysis": true
    }
  ]
}

Configuration Schema

Parameter Type Default Description
name string required Unique identifier for the tripwire
group string "default" Logical group for batch processing
vertices array required Array of points defining the line segments
direction string "Both" Crossing direction ("Both", "Up", "Down")
color array [1,0,0,1] RGBA color for visualization
bandwidth float 10.0 Sensitivity zone width around the line
min_crossing_time float 0.5 Minimum time to validate a crossing
max_crossing_time float 10.0 Maximum time to complete a crossing
tailgating_threshold float 3.0 Time threshold for tailgating detection
enabled bool true Enable/disable the tripwire
sensitivity float 1.0 Crossing sensitivity multiplier
min_track_hits int 2 Minimum track confirmations for crossing
speed_analysis bool false Enable speed calculation for crossings

API Reference

C++ API (TripwireManaged)

Tripwire Management

expected<std::string> createTripwire(std::string const& name, std::string const& group,
                                     std::vector<Point2f> const& shape,
                                     std::array<float, 4> const& color,
                                     std::string direction = "Both")
  • Parameters: Name, group, line vertices, color, crossing direction
  • Returns: Expected tripwire ID string
  • Usage: Create new tripwire with specified configuration

Processing Operations

expected<void> processTripwires(std::map<std::string, std::vector<Point2f>> const& points,
                               cmap const& options = {})
expected<void> processTripwires(std::map<std::string, std::vector<Point2f>> const& points,
                               std::vector<std::string> const& tripwiresFilter,
                               cmap const& options = {})
expected<void> processTripwires(std::map<std::string, std::vector<Point2f>> const& points,
                               std::string const& groupFilter,
                               cmap const& options = {})
  • Parameters: Track points, optional filters, processing options
  • Returns: Expected void, generates crossing events internally
  • Usage: Process tracked objects against tripwire definitions

Tripwire Queries

bool hasTripwireId(std::string const& tripwireId)
expected<std::vector<std::string>> getTripwireIds()
expected<pCValue> getTripwireById(std::string tripwireId, int dictType = DICT_STATE)
expected<cmap> getTripwires(int dictType = DICT_STATE)
  • Existence Check: Verify tripwire exists by ID
  • ID Retrieval: Get all tripwire identifiers
  • Data Access: Retrieve tripwire configuration and state data

Value Management

expected<pCValue> getTripwireValue(std::string const& tripwireId, std::string const& key,
                                  int dictType = DICT_STATE)
expected<void> setTripwireValue(std::string const& tripwireId, std::string const& key,
                               pCValue const& value, int dictType = DICT_STATE)
expected<void> setTripwireValue(std::string const& tripwireId, cmap const& values,
                               int dictType = DICT_STATE)
  • Property Access: Get and set individual tripwire properties
  • Batch Updates: Set multiple properties simultaneously
  • State Management: Access both configuration and runtime state

Lifecycle Management

expected<void> registerKnownTripwires(bool skipRecalculate = false)
expected<void> recalculateTripwire(std::string const& tripwireId)
expected<void> recalculateTripwires()
expected<void> deleteTripwireById(std::string const& tripwireId)
expected<void> resetTripwires()
expected<void> deleteTripwires()
  • Registration: Register tripwires from configuration
  • Recalculation: Update tripwire geometry and parameters
  • Cleanup: Remove specific tripwires or reset entire system

Event Handling

expected<void> registerCallback(sol::protected_function callback)
expected<void> unregisterCallback()
expected<cvec> getTripwireEvents()
  • Callback Registration: Set Lua callback for crossing events
  • Event Retrieval: Get generated crossing events for processing

Lua API

Factory Methods

-- Create tripwire manager
local tripwire = api.factory.tripwire.create(instance, "security_tripwires")

-- Get existing tripwire manager
local tripwire = api.factory.tripwire.get(instance, "security_tripwires")

Basic Operations

-- Create tripwire
local tripwireId = tripwire:createTripwire(
    "entrance_line",
    "security",
    {{x = 100, y = 200}, {x = 300, y = 200}},
    {1.0, 0.0, 0.0, 1.0},
    "Both"
)

-- Register callback for crossing events
tripwire:registerCallback(function(event)
    print("Crossing detected:", event.tripwire_id, event.track_id, event.direction)
end)

-- Process tracks against tripwires
local trackPoints = {
    ["track_1"] = {{x = 150, y = 180}, {x = 160, y = 185}}
}
tripwire:processTripwires(trackPoints)

Examples

Basic Line Crossing Detection

#include "tripwiremanaged.h"

// Create tripwire manager
auto tripwire = TripwireManaged::create("entrance_detection");

// Define entrance line
std::vector<Point2f> entranceLine = {
    {100.0f, 200.0f}, {300.0f, 200.0f}
};

std::array<float, 4> redColor = {1.0f, 0.0f, 0.0f, 1.0f};

// Create bidirectional tripwire
auto result = tripwire->createTripwire(
    "main_entrance", "security", entranceLine, redColor, "Both");

if (result) {
    std::string tripwireId = result.value();

    // Register crossing event callback
    tripwire->registerCallback([](sol::table event) {
        std::string trackId = event["track_id"];
        std::string direction = event["direction"];
        double timestamp = event["timestamp"];

        LOGI << "Track " << trackId << " crossed " << direction
             << " at " << timestamp;

        // Process crossing event
        handleCrossingEvent(trackId, direction, timestamp);
    });

    // Process frame with tracked objects
    while (videoStream.hasFrame()) {
        auto tracks = tracker->getTracks();

        // Extract track positions
        std::map<std::string, std::vector<Point2f>> trackPoints;
        for (const auto& [id, track] : tracks) {
            Point2f center = {
                track->bbox.x + track->bbox.width / 2.0f,
                track->bbox.y + track->bbox.height / 2.0f
            };
            trackPoints[std::to_string(id)] = {center};
        }

        // Process tripwires
        tripwire->processTripwires(trackPoints);
    }
}

Multi-Segment Perimeter Detection

// Create complex perimeter with multiple segments
std::vector<Point2f> perimeterLine = {
    {50.0f, 100.0f},   // Start point
    {200.0f, 120.0f},  // Middle point 1
    {350.0f, 110.0f},  // Middle point 2
    {500.0f, 130.0f}   // End point
};

auto perimeterTripwire = TripwireManaged::create("perimeter_detection");

// Create unidirectional tripwire (inward only)
auto perimeterId = perimeterTripwire->createTripwire(
    "security_perimeter", "restricted", perimeterLine,
    {1.0f, 0.5f, 0.0f, 1.0f}, "Up");

if (perimeterId) {
    // Configure advanced parameters
    perimeterTripwire->setTripwireValue(perimeterId.value(), "bandwidth", CValue::create(20.0));
    perimeterTripwire->setTripwireValue(perimeterId.value(), "min_crossing_time", CValue::create(1.0));
    perimeterTripwire->setTripwireValue(perimeterId.value(), "tailgating_threshold", CValue::create(3.0));

    // Enable speed analysis
    perimeterTripwire->setTripwireValue(perimeterId.value(), "speed_analysis", CValue::create(true));

    // Register advanced callback
    perimeterTripwire->registerCallback([](sol::table event) {
        std::string trackId = event["track_id"];
        std::string tripwireId = event["tripwire_id"];
        std::string direction = event["direction"];
        double crossingSpeed = event.get_or("speed", 0.0);
        bool isTailgating = event.get_or("tailgating", false);

        if (isTailgating) {
            LOGW << "Tailgating detected on " << tripwireId << ": " << trackId;
            generateSecurityAlert("TAILGATING", trackId, tripwireId);
        }

        if (crossingSpeed > 5.0) {  // Fast movement
            LOGW << "Fast crossing detected: " << crossingSpeed << " units/sec";
            generateSecurityAlert("FAST_MOVEMENT", trackId, tripwireId);
        }

        // Log all crossings
        logSecurityEvent(trackId, tripwireId, direction, crossingSpeed);
    });
}

Lua-Based Traffic Monitoring

-- Traffic monitoring system with multiple tripwires
local tripwire = api.factory.tripwire.create(instance, "traffic_monitor")

-- Define traffic counting lines
local trafficLines = {
    {
        name = "lane_1_counter",
        group = "traffic",
        vertices = {{x = 100, y = 300}, {x = 200, y = 310}},
        direction = "Up"
    },
    {
        name = "lane_2_counter", 
        group = "traffic",
        vertices = {{x = 220, y = 315}, {x = 320, y = 325}},
        direction = "Up"
    },
    {
        name = "pedestrian_crossing",
        group = "pedestrian",
        vertices = {{x = 150, y = 400}, {x = 350, y = 420}},
        direction = "Both"
    }
}

-- Create tripwires
local tripwireIds = {}
for _, line in ipairs(trafficLines) do
    local id = tripwire:createTripwire(
        line.name,
        line.group,
        line.vertices,
        {0.0, 1.0, 0.0, 1.0},  -- Green color
        line.direction
    )

    if id then
        tripwireIds[line.name] = id

        -- Configure for traffic monitoring
        tripwire:setTripwireValue(id, "bandwidth", 25.0)
        tripwire:setTripwireValue(id, "min_crossing_time", 0.8)
        tripwire:setTripwireValue(id, "speed_analysis", true)
    end
end

-- Traffic counting variables
local trafficStats = {
    lane_1 = {count = 0, last_crossing = 0},
    lane_2 = {count = 0, last_crossing = 0},
    pedestrian = {count = 0, last_crossing = 0}
}

-- Register crossing callback
tripwire:registerCallback(function(event)
    local tripwireId = event.tripwire_id
    local trackId = event.track_id
    local direction = event.direction
    local timestamp = event.timestamp
    local speed = event.speed or 0

    print(string.format("Traffic crossing: %s on %s, direction: %s, speed: %.2f",
                       trackId, tripwireId, direction, speed))

    -- Update statistics
    if tripwireId == tripwireIds.lane_1_counter then
        trafficStats.lane_1.count = trafficStats.lane_1.count + 1
        trafficStats.lane_1.last_crossing = timestamp
    elseif tripwireId == tripwireIds.lane_2_counter then
        trafficStats.lane_2.count = trafficStats.lane_2.count + 1
        trafficStats.lane_2.last_crossing = timestamp
    elseif tripwireId == tripwireIds.pedestrian_crossing then
        trafficStats.pedestrian.count = trafficStats.pedestrian.count + 1
        trafficStats.pedestrian.last_crossing = timestamp
    end

    -- Speed analysis
    if speed > 15.0 then  -- High speed threshold
        print("Warning: High speed detected: " .. speed .. " on " .. tripwireId)
        -- Generate speed alert
    end

    -- Generate traffic report every 100 crossings
    local totalCrossings = trafficStats.lane_1.count + 
                          trafficStats.lane_2.count + 
                          trafficStats.pedestrian.count

    if totalCrossings % 100 == 0 then
        generateTrafficReport(trafficStats)
    end
end)

-- Main processing function
function processTrafficFrame(tracks)
    -- Convert tracks to point format
    local trackPoints = {}

    for trackId, track in pairs(tracks) do
        if track.state == "active" then
            local center = {
                x = track.bbox.x + track.bbox.w / 2,
                y = track.bbox.y + track.bbox.h / 2
            }
            trackPoints[tostring(trackId)] = {center}
        end
    end

    -- Process all tripwires
    tripwire:processTripwires(trackPoints)
end

Best Practices

Tripwire Placement

  • Perpendicular Positioning: Place lines perpendicular to expected object movement
  • Adequate Length: Ensure lines span the full width of the monitoring area
  • Bandwidth Sizing: Set bandwidth 2-3 times larger than typical object width
  • Multi-Segment Lines: Use multiple segments for complex boundaries

Configuration Optimization

  • Direction Setting: Use unidirectional detection when appropriate to reduce false positives
  • Timing Parameters: Adjust min_crossing_time based on expected object speeds
  • Sensitivity Tuning: Fine-tune bandwidth and sensitivity for specific scenarios
  • Group Organization: Use groups for logical separation and batch processing

Integration Guidelines

  • Tracking Dependency: Ensure reliable object tracking before tripwire processing
  • Event Handling: Process crossing events promptly to avoid memory buildup
  • State Management: Regularly clean up old tripwire states and events
  • Performance: Use group filtering to process only relevant tripwires

Troubleshooting

Common Issues

False Positive Crossings

// Increase minimum crossing time
tripwire->setTripwireValue(tripwireId, "min_crossing_time", CValue::create(1.0));

// Reduce bandwidth sensitivity
tripwire->setTripwireValue(tripwireId, "bandwidth", CValue::create(8.0));

// Increase minimum track hits
tripwire->setTripwireValue(tripwireId, "min_track_hits", CValue::create(3));

Missed Crossings

// Increase bandwidth for wider detection zone
tripwire->setTripwireValue(tripwireId, "bandwidth", CValue::create(15.0));

// Reduce minimum crossing time
tripwire->setTripwireValue(tripwireId, "min_crossing_time", CValue::create(0.3));

// Enable bidirectional detection
tripwire->setTripwireValue(tripwireId, "direction", CValue::create("Both"));

Performance Issues

  • Group Filtering: Process only active tripwire groups
  • Track Filtering: Pre-filter tracks by area of interest
  • Event Cleanup: Regularly clear processed events
  • Geometry Optimization: Simplify complex multi-segment lines

Debugging Tools

// Monitor tripwire statistics
auto tripwires = tripwire->getTripwires(DICT_STATE);
for (const auto& [id, data] : tripwires.value()) {
    auto crossingCount = tripwire->getTripwireValue(id, "crossing_count", DICT_STATE);
    auto lastCrossing = tripwire->getTripwireValue(id, "last_crossing_time", DICT_STATE);

    LOGI << "Tripwire " << id << ": " 
         << crossingCount.value()->getInt() << " crossings, "
         << "last: " << lastCrossing.value()->getDouble();
}

// Check for events
auto events = tripwire->getTripwireEvents();
LOGI << "Pending events: " << events.value().size();

Integration Examples

Security System Integration

// Complete security monitoring system
class SecurityMonitoringSystem {
private:
    std::shared_ptr<TripwireManaged> tripwires_;
    std::shared_ptr<ZoneManaged> restrictedZones_;
    std::shared_ptr<TrackerManaged> tracker_;

public:
    void initialize() {
        // Initialize components
        tripwires_ = std::dynamic_pointer_cast<TripwireManaged>(
            TripwireManaged::create("security_tripwires"));
        restrictedZones_ = ZoneManaged::create("restricted_areas");
        tracker_ = TrackerManaged::create("security_tracker");

        // Create perimeter tripwires
        setupPerimeterTripwires();

        // Register security event callback
        tripwires_->registerCallback([this](sol::table event) {
            handleSecurityCrossing(event);
        });
    }

    void processSecurityFrame(const cbuffer& frame,
                             const std::vector<Detection>& detections) {
        // Update tracking
        auto tracks = updateTracking(frame, detections);

        // Extract track positions for analysis
        std::map<std::string, std::vector<Point2f>> trackPoints;
        extractTrackPositions(tracks, trackPoints);

        // Process security analytics
        tripwires_->processTripwires(trackPoints, "security");
        restrictedZones_->processZones(trackPoints, "restricted");

        // Generate alerts for security events
        processSecurityAlerts();
    }

private:
    void setupPerimeterTripwires() {
        // Main entrance
        std::vector<Point2f> entrance = {{100, 200}, {300, 200}};
        tripwires_->createTripwire("main_entrance", "security", 
                                  entrance, {1,0,0,1}, "Both");

        // Emergency exits (outbound only)
        std::vector<Point2f> emergency = {{500, 400}, {600, 420}};
        tripwires_->createTripwire("emergency_exit", "security",
                                  emergency, {1,0.5,0,1}, "Down");
    }
};

See Also