Skip to main content

Challenge 30: Spatial Analysis

Estimated Time

45 min | Cost: $2-5 (estimated) | Domain: Implement Computer Vision Solutions (10-15%)

Edge Deployment

Spatial Analysis typically runs as an IoT Edge module on edge hardware with a connected camera. This challenge covers the configuration and output format. Actual deployment requires compatible hardware.

Exam skills covered

  • Implement spatial analysis for detecting presence and movement
  • Configure zones and lines for people counting
  • Process spatial analysis events

Overview

Azure AI Vision Spatial Analysis processes real-time video from cameras to understand people's movements and interactions with physical spaces:

OperationDescription
cognitiveservices.vision.spatialanalysis-personcountCount people in a zone
cognitiveservices.vision.spatialanalysis-personcrossinglineDetect when people cross a line
cognitiveservices.vision.spatialanalysis-personcrossingpolygonDetect entry/exit from a polygon zone
cognitiveservices.vision.spatialanalysis-persondistanceMonitor social distancing
cognitiveservices.vision.spatialanalysis-personzonedwelltimeMeasure time spent in zones

Deployment model: Video → IoT Edge device (Spatial Analysis container) → IoT Hub → Application

Prerequisites

  • Azure subscription
  • Azure AI Vision resource (S1 tier for Spatial Analysis)
  • Understanding of IoT Edge deployment (conceptual)
  • Azure IoT Hub

Implementation

Task 1: Create IoT Hub and Register Edge Device

az group create --name rg-ai102-spatial --location eastus2

# Create Computer Vision resource (S1 tier required for Spatial Analysis)
az cognitiveservices account create \
--name cv-spatial-ai102 \
--resource-group rg-ai102-spatial \
--kind ComputerVision \
--sku S1 \
--location eastus2

# Create IoT Hub
az iot hub create \
--name iothub-spatial-ai102 \
--resource-group rg-ai102-spatial \
--sku S1 \
--location eastus2

# Register IoT Edge device
az iot hub device-identity create \
--hub-name iothub-spatial-ai102 \
--device-id edge-spatial-device \
--edge-enabled

# Get connection string for device provisioning
az iot hub device-identity connection-string show \
--hub-name iothub-spatial-ai102 \
--device-id edge-spatial-device \
--output tsv

Task 2: Configure Spatial Analysis Operation

import json

# Spatial Analysis is configured via deployment manifest for IoT Edge
# This shows the configuration structure and event processing

# Zone definition for people counting
zone_config = {
"zones": [
{
"name": "entrance-zone",
"polygon": [
[0.1, 0.1], # top-left (normalized coordinates)
[0.6, 0.1], # top-right
[0.6, 0.9], # bottom-right
[0.1, 0.9] # bottom-left
]
},
{
"name": "checkout-zone",
"polygon": [
[0.65, 0.2],
[0.95, 0.2],
[0.95, 0.8],
[0.65, 0.8]
]
}
]
}

# Line definition for crossing detection
line_config = {
"lines": [
{
"name": "entry-line",
"line": {
"start": [0.5, 0.0],
"end": [0.5, 1.0]
},
"direction": {
"to": "right",
"from": "left"
}
}
]
}

# Full operation configuration
spatial_analysis_config = {
"ai_parameters": {
"OPERATION_NAME": "cognitiveservices.vision.spatialanalysis-personcount",
"CAMERA_CONFIGURATION": json.dumps({
"gpu_index": 0,
"camera_id": "camera-01",
"zones": zone_config["zones"]
}),
"DETECTOR_NODE_CONFIG": json.dumps({
"gpu_index": 0,
"detector_node_name": "person-detector",
"min_confidence": 0.7,
"enable_face_mask_classifier": True
}),
"SPACEANALYTICS_CONFIG": json.dumps({
"zones": zone_config["zones"],
"events": {
"PERSON_COUNT": {
"trigger": "event",
"output_frequency": 1,
"threshold": 5
}
}
})
}
}

print("Spatial Analysis Configuration:")
print(json.dumps(spatial_analysis_config, indent=2))

Task 3: IoT Edge Deployment Manifest

# IoT Edge deployment manifest for Spatial Analysis
deployment_manifest = {
"modulesContent": {
"$edgeAgent": {
"properties.desired": {
"schemaVersion": "1.1",
"runtime": {
"type": "docker",
"settings": {
"minDockerVersion": "v1.25"
}
},
"systemModules": {
"edgeAgent": {
"type": "docker",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-agent:1.4"
}
},
"edgeHub": {
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-hub:1.4"
}
}
},
"modules": {
"spatialanalysis": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/azure-cognitive-services/vision/spatial-analysis:latest",
"createOptions": json.dumps({
"HostConfig": {
"Runtime": "nvidia",
"Binds": [
"/tmp/.X11-unix:/tmp/.X11-unix"
],
"IpcMode": "host"
},
"Env": [
"DISPLAY=:0"
]
})
}
}
}
}
},
"$edgeHub": {
"properties.desired": {
"schemaVersion": "1.1",
"routes": {
"spatialToHub": "FROM /messages/modules/spatialanalysis/outputs/* INTO $upstream"
},
"storeAndForwardConfiguration": {
"timeToLiveSecs": 7200
}
}
},
"spatialanalysis": {
"properties.desired": {
"globalSettings": {
"PlatformTelemetryEnabled": True,
"CustomerTelemetryEnabled": True
},
"graphs": {
"personcount": {
"operationId": "cognitiveservices.vision.spatialanalysis-personcount",
"version": 2,
"enabled": True,
"parameters": {
"VIDEO_URL": "rtsp://camera-ip:554/stream",
"VIDEO_SOURCE_ID": "camera-01",
"SPACEANALYTICS_CONFIG": json.dumps({
"zones": [{
"name": "entrance",
"polygon": [[0.1,0.1],[0.9,0.1],[0.9,0.9],[0.1,0.9]],
"events": [{
"type": "count",
"config": {
"trigger": "event",
"threshold": 3,
"focus": "footprint"
}
}]
}]
})
}
}
}
}
}
}
}

print("Deployment Manifest (partial):")
print(json.dumps(deployment_manifest["modulesContent"]["spatialanalysis"], indent=2)[:1000])

Task 4: Process Spatial Analysis Events

# Process events from Spatial Analysis (via IoT Hub)
# These are the event structures emitted by the spatial analysis module

sample_events = [
{
"id": "event-001",
"type": "personCountEvent",
"detectionIds": ["det-1", "det-2", "det-3"],
"properties": {
"personCount": 3,
"zone": "entrance-zone",
"trigger": "event"
},
"sourceInfo": {
"id": "camera-01",
"timestamp": "2024-01-15T10:30:00.000Z",
"width": 1920,
"height": 1080,
"frameId": "frame-4521"
}
},
{
"id": "event-002",
"type": "personCrossingLineEvent",
"detectionIds": ["det-4"],
"properties": {
"direction": "in",
"line": "entry-line",
"zone": "entrance-zone"
},
"sourceInfo": {
"id": "camera-01",
"timestamp": "2024-01-15T10:30:05.000Z",
"width": 1920,
"height": 1080,
"frameId": "frame-4530"
}
},
{
"id": "event-003",
"type": "personDistanceEvent",
"detectionIds": ["det-5", "det-6"],
"properties": {
"personCount": 2,
"minimumDistanceInFeet": 3.2,
"averageDistanceInFeet": 4.8,
"violationCount": 1,
"zone": "checkout-zone"
},
"sourceInfo": {
"id": "camera-01",
"timestamp": "2024-01-15T10:30:10.000Z",
"width": 1920,
"height": 1080,
"frameId": "frame-4540"
}
}
]

# Event processor
class SpatialEventProcessor:
def __init__(self):
self.zone_counts = {}
self.crossings = {"in": 0, "out": 0}
self.distance_violations = 0

def process_event(self, event):
event_type = event["type"]
props = event["properties"]
timestamp = event["sourceInfo"]["timestamp"]

if event_type == "personCountEvent":
zone = props["zone"]
count = props["personCount"]
self.zone_counts[zone] = count
print(f"[{timestamp}] ZONE '{zone}': {count} people")

if count > 5:
print(f" ⚠️ ALERT: Zone '{zone}' exceeds capacity!")

elif event_type == "personCrossingLineEvent":
direction = props["direction"]
self.crossings[direction] = self.crossings.get(direction, 0) + 1
print(f"[{timestamp}] LINE CROSSING: 1 person going '{direction}' at '{props['line']}'")

elif event_type == "personDistanceEvent":
violations = props["violationCount"]
self.distance_violations += violations
min_dist = props["minimumDistanceInFeet"]
print(f"[{timestamp}] DISTANCE: {props['personCount']} people, "
f"min distance: {min_dist:.1f}ft, violations: {violations}")

def summary(self):
print(f"\n--- Session Summary ---")
print(f"Zone occupancy: {self.zone_counts}")
print(f"Crossings: {self.crossings}")
print(f"Distance violations: {self.distance_violations}")

# Process sample events
processor = SpatialEventProcessor()
for event in sample_events:
processor.process_event(event)
processor.summary()

Expected Output

Spatial Analysis Configuration:
{
"ai_parameters": {
"OPERATION_NAME": "cognitiveservices.vision.spatialanalysis-personcount",
...
}
}

[2024-01-15T10:30:00.000Z] ZONE 'entrance-zone': 3 people
[2024-01-15T10:30:05.000Z] LINE CROSSING: 1 person going 'in' at 'entry-line'
[2024-01-15T10:30:10.000Z] DISTANCE: 2 people, min distance: 3.2ft, violations: 1

--- Session Summary ---
Zone occupancy: {'entrance-zone': 3}
Crossings: {'in': 1, 'out': 0}
Distance violations: 1

Break & fix

ScenarioSymptomRoot CauseFix
No events generatedModule running but silentCamera feed URL incorrect or unreachableVerify RTSP URL; check network connectivity
False detectionsHigh person count in empty areaMin confidence too lowIncrease min_confidence in detector config
Zone not triggeringEvents for wrong zonePolygon coordinates incorrectVerify normalized coordinates match camera FOV
GPU out of memoryContainer crashesToo many simultaneous operationsReduce number of zones/operations per GPU
Delayed eventsHigh latencyEdge hardware underpoweredUse recommended GPU (NVIDIA T4 or better)

Knowledge Check

1. How is Spatial Analysis deployed?

2. How are zones defined in Spatial Analysis configuration?

3. Which operation would you use to count how many people are in a store section?

4. What triggers a 'personCrossingLine' event?

5. What hardware is required for Spatial Analysis?

Cleanup

az group delete --name rg-ai102-spatial --yes --no-wait

Learn More