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");
}
};