This articles gives a short introduction to scripting alarm and counter tasks with Intelligent and Essential Video Analytics in FW 7.60. It also provides a broad selection of example scripts for explanation as well as including real world application examples.
VCA stands for video content analysis. The VCA task script language:
The VCA task scripts are used implicitly whenever an Intelligent Video Analytics, Essential Video Analytics or MOTION+ task is configured via the GUI. However, manual configuration of the VCA task scripts is also possible and advised whenever the predefined tasks are not enough:
(1) Define all tasks via task wizards as far as possible.
(2) Change to the VCA task script editor. The already defined tasks can be found there with all details.
(3) Make your modifications.
(4) Change the defined tasks into task type scripted so accidental use of the task wizards will not overwrite your changes.
Go to the Intelligent Video Analytics, Essential Video Analytics or MOTION+ configuration and open the task page.
Right-click on the video and select Advanced -> VCA Task Editor. A separate popup with the current VCA task script will appear:
A task consists of
Note that not all tasks and filters are available in every FW version.
MOTION+:
Intelligent Video Analytics & Essential Video Analytics (the latter w/o flow tasks):
From the task primitives, the tasks and the object filter as defined in the GUI via the task wizards, target object states and events are derived. These can also be defined directly in the VCA task script language.
Events are always temporal relations
States can be, amongst others, spatial relations, object properties, tamper states, counter values
Events and states can be internal or external. Only external events and states are outputted.
Simple states are used whenever a property has no corresponding objects. Examples are Motion+, Flow, counter values and tamper states.
The combinations of object states and events listed below are possible. Object states can be also converted into events, but only the onset or leaving of an object state is an actual event, not the actual duration of the object in this state.
Starting with FW 6.60 and in order to create temporary states triggered by an event, the keyword within can used after an event. This can be used to
- delay or debounce an alarm based on an object state: within(0,)
- to extend an alarm state similarly to the aggregation time: within(,*)
- debouncing object properties: By checking the target values is currently met, and has not changed during the debounce time
- temporarily combine an event with other states
There are two different ways to describe the position information of lines, fields and routes:
Here, the coordinates are defined within the specified resolution and transferred automatically to the real resolution used in the video analytics.
//Definition of task primitives Line #1 := { Point(103, 30) Point(159, 77)}; Line #2 := { Point(26, 65) Point(82, 122) DebounceTime(0.50) Direction(1) }; //Definition of alarm task shown in GUI //@Task T:2 V:0 I:1 "Crossing line 1" { //[1.a=s1:1;1.b=1;1.c=32;1.d=31;4.a=i:1;] external Event#1 :={CrossedLine#1}; //@} //Definition of self-defined task shown in GUI //@Task T:0 V:0 I:2 "Crossing line 2" { external Event#2 :={CrossedLine#2}; //@} //Definition of alarm task not shown in GUI external Event#3 :={CrossedLine#2}; |
//Definition of task primitives Resolution := { Min(-1, -1) Max(1, 1) }; Line #1 := { Point(-0.85, 0.95) Point(-0.6, 0.4) Point(0.6, 0.4) Point(0.85, 0.95) DebounceTime(0.50) Direction(2) TriggerPoint(FootPoint) }; //Definition of alarm task shown in GUI //@Task T:2 V:0 I:1 "Crossing line 1" { //[1.a=s1:1;1.b=1;1.c=32;1.d=31;4.a=i:1;] external Event#1 :={CrossedLine#1}; //@} |
|
//Definition of task primitives Line #1 := { Point(103, 30) Point(159, 77)}; //@Task T:2 V:0 I:1 "Crossing line 1" { //[1.a=s1:1;1.b=1;1.c=32;1.d=31;3.o=(b1:1, b2:0.1,b3:500, c1:1,c2:0.02,c3:34.00,d1:1, d2:0,d3:27.78,e1:1,e2:315, e3:45,f1:1,f2:135, f3:225);4.a=(c:2b19,i:1,pr:2);5.a=(c:1,p:1); 6.a=(d1:8,d2:33,r:2,u:1);] ColorHistogram #1:= { HSV(60,38,100,25) Similarity(75) Outlier(75) }; external Event#1:={CrossedLine#1 where ObjectSize within(0.1,500) and AspectRatio within(0.02,34.00) and Velocity within(0,27.78) and (Direction within(315,405) or Direction within(135,225)) and SimilarToColor #1 and HadFace and MaxFaceWidth within(8,33)}; //@} |
|
//Definition of task primitives Field #1 := { Point(56, 24) Point(106, 24) Point(106, 74)}; Field #2 := { Point(56, 24) Point(106, 24) Point(106, 74) Point(56, 74) DebounceTime(0.50) ObjectSet(BoundingBox) SetRelation(Covering)}; //@Task T:1 V:0 I:1 "Object in field 1" { //[1.a=1;1.b=1;3.a=i:1;] external ObjectState #1 := InsideField #1; //@} |
|
//Definition of task primitives Route #1 := { Point(34, 111) Distance(5) Point(92, 125) Distance(5) Point(140, 104) Distance(5) Point(143, 72) Distance(5) MinPercentage(80) MaxGap(10) }; //@Task T:6 V:0 I:1 "Follow route 1" { //[1.a=id:1;1.b=1;3.a=i:1;] external Event #1 := { FollowedRoute #1 }; //@} |
|
//Definition of task primitives Resolution := { Min(-1, -1) Max(1, 1) }; Field #1 := { Point(-0.6, 0.95) Point(-0.25, -0.95) Point(0.25, -0.95) Point(0.6, 0.95) DebounceTime(0.50) }; Line #1 := { Point(0.0, -0.95) Point(0.0, 0.95) DebounceTime(0.50) }; //@Task T:0 V:0 I:1 "Enter Field and Line" { external Event#1:={EnteredField #1 before (*,30) CrossedLine #1 where first.oid == second.oid }; //@} |
|
//Definition of task primitives Resolution := { Min(-1, -1) Max(1, 1) }; Field #1 := { Point(-0.6, 0.95) Point(-0.25, -0.95) Point(-0.1, -0.95) Point(-0.1, 0.95) DebounceTime(0.50) }; Field #2 := { Point(0.6, 0.95) Point(0.25, -0.95) Point(0.1, -0.95) Point(0.1, 0.95) DebounceTime(0.50) }; //@Task T:0 V:0 I:1 "Enter Field and Line" { external Event#1:={EnteredField #1 before (*,30) EnteredField#2 where first.oid == second.oid }; //@} |
|
//Definition of task primitives Resolution := { Min(-1, -1) Max(1, 1) }; Field #1 := { Point(0.406, -0.644) Point(0.250, -0.656) Point(-0.213, 1.000) Point(0.400, 1.000) DebounceTime(0.10) }; Field #2 := { Point(0.181, -0.667) Point(-0.388, 1.000) Point(-0.588, 1.000) Point(0.088, -0.678) DebounceTime(0.10) }; //@Task T:0 V:0 I:1 " Field combination" { ObjectState #16 := InsideField #1 and ObjectSize within(0.7,10) ; ObjectState #17 := InsideField #2 and ObjectSize within(0.7,10) ; external Event #1 := { OnSet ObjectState #16 before OnSet ObjectState #17 where first.oid==second.oid}; //@} |
|
//Definition of task primitives Line #1 := { Point(0, 90) Point(60, 90) DebounceTime(0.10) Direction(1) }; Line #2 := { Point(60, 90) Point(90, 60) DebounceTime(0.10) Direction(1) }; Line #3 := { Point(90, 60) Point(90, 0) DebounceTime(0.10) Direction(1) }; //@Task T:0 V:0 I:1 "Counter 1" { Event#32 :=CrossedLine#1 or CrossedLine#2 or CrossedLine#3; external Counter#1 := { Event#32 Text("Corner Count1:") TopLeft(4,4) Mode(Wraparound) within(0,999999999) }; //@} |
|
//Definition of task primitives Line #1 := {Point(50,0) Point(50,144)}; Line #2 := {Point(120,0) Point(120,144)}; //Definition of line crossing events Event#11 :={CrossedLine#1 where Velocity within(13.89,19.44) }; Event#12 :={CrossedLine#2 where Velocity within(2.778,5.556) }; //Combination of line crossing events //@Task T:0 V:0 I:1 "Two Line Speed Check" { external Event#1 :={Event#11 before Event#12 where first.oid==second.oid}; //@} |
|
//Definition of task primitives Line #1 := { Point(130, 0) Point(130, 144) }; Field #2 := { Point(50, 0) Point(115, 0) Point(115, 144) Point(50, 144)}; //@Task T:0 V:0 I:1 "Loitering after Line Crossing" { Event#11 :={CrossedLine #1}; Loitering #13 := { Radius (15) Time (10) }; ObjectState #14 := InsideField #2 and IsLoitering #13; external Event #1 := {Event #11 before OnSet ObjectState #14 where first.oid==second.oid}; //@} |
|
//Definition of task primitives Field #1 := { Point(100, 0) Point(175, 0) Point(175, 144) Point(100, 144) ObjectSet(BoundingBox)}; //@Task T:0 V:0 I:1 "Object Touches Field" { ObjectState #1 := InsideField #1; external Event #1 := OnSet ObjectState #1; //@} //Alternative, objects have to come from the outside of the field: //@Task T:0 V:0 I:2 "Object Touches Field" { external Event #2 := EnteredField #1; //@} |
|
//Definition of task primitives Resolution := { Min(-1, -1) Max(1, 1) }; Field #1 := { Point(-0.244, -0.922) Point(0.325, -0.944) Point(0.350, 0.944) Point(-0.231, 0.944) DebounceTime(0.50) }; //@Task T:0 V:0 I:1 "Thieve detection" { Event #11 :={EnteredField #1 before EnteredField #1 where first.oid==second.oid}; Event #12 :={Event #11 before EnteredField #1 where first.oid==second.oid}; external Event#1 :={Event #12 before EnteredField #1 where first.oid==second.oid}; //@} |
|
//Definition of task primitives Resolution := { Min(-1, -1) Max(1, 1) }; Line #1 := { Point(-0.187, -0.967) Point(-0.156, 0.911) DebounceTime(0.50) Direction(2) TriggerPoint(FootPoint) }; //@Task T:0 V:0 I:1 "Tailgaiting" { Event#21:={CrossedLine#1}; Event#22:={CrossedLine#1}; external Event#1:={Event#21 before(0,3) Event#22 where first.oid!=second.oid}; //@} |
|
//Definition of task primitives Resolution := { Min(-1, -1) Max(1, 1) }; Field #1 := { Point(-0.656, -0.700) Point(0.350, -0.767) Point(0.469, 0.644) Point(-0.694, 0.644) DebounceTime(0.10) }; //@Task T:0 V:0 I:1 "Alarm on more than two objects" { external ObjectState #1:= ObjectsInField#1 within (2,*); //@} |
|
//Definition of task primitives Resolution := { Min(-1, -1) Max(1, 1) }; Field #1 := { Point(-0.656, -0.700) Point(0.350, -0.767) Point(0.469, 0.644) Point(-0.694, 0.644) DebounceTime(0.10) }; //@Task T:0 V:0 I:1 "Count of objects in field " { external Counter#1 := { ObjectsInField#1 Text("Counter:") TopLeft(-0.975,-0.844) }; //@} //@Task T:18 V:0 I:2 "Count of objects in field " { //[1.a=1;1.b=1;1.c=32;2.a=(,b3:1);] ObjectState #32 := InsideField #1; external Counter#2 := { ObjectsInState#32 Text("Occupancy:") TopLeft(-0.975,-0.744) }; //@} |
|
//Definition of task primitives Resolution:= { Min(-1, -1) Max(1, 1) }; Field #1:= { Point(-0.150, -0.700) Point(0.250, -0.700) Point(0.250, 0.600) Point(-0.150, 0.600) DebounceTime(0.10) }; Field #2:= { Point(-0.600, -0.700) Point(-0.200, -0.700) Point(-0.200, 0.600) Point(-0.600, 0.600) DebounceTime(0.10) }; //@Task T:0 V:0 I:1 "Unmanned reception" { external SimpleState #1:= ObjectsInField#1 within (1,*) and ObjectsInField#2 within (0,0); //@} |
|
//Definition of task primitives Resolution:= { Min(-1, -1) Max(1, 1) }; Field #1:= { Point(-0.150, -0.700) Point(0.250, -0.700) Point(0.250, 0.600) Point(-0.150, 0.600) DebounceTime(0.10) }; Field #2:= { Point(-0.600, -0.700) Point(-0.200, -0.700) Point(-0.200, 0.600) Point(-0.600, 0.600) DebounceTime(0.10) }; //@Task T:0 V:0 I:1 "Only one queue" { ObjectState #1:= ObjectsInField#1 within (3,*); external Event #1:= {OnSet ObjectState #1 where ObjectsInField#2 within (0,0)}; //@} // To see the results of the no object check, use the following: //@Task T:0 V:0 I:2 "No object" { external SimpleState #2:= ObjectsInField#2 within (0,0); //@} |
|
//Definition of task primitives Resolution:= { Min(-1, -1) Max(1, 1) }; Line #1 := { Point(-0.1, -0.8) Point(-0.1, 0.8) DebounceTime(0.10) Direction(1) }; Line #2 := { Point(0.1, 0.8) Point(0.1, -0.8) DebounceTime(0.10) Direction(1) }; //@Task T:0 V:0 I:1 "Virtual Room" { Event#31:={CrossedLine#1}; Event#30:={CrossedLine#2}; external Counter#1 := { Event#31 Text("Linie 1:") TopLeft(4,4) }; external Counter#2 := { Event#30 Text("Linie 2:") TopLeft(4,14) }; external Counter#4 := { Counter#1 - Counter#2 Text("Virtual Room:") TopLeft(4,34) }; //@} |
|
//Definition of task primitives Resolution:= { Min(-1, -1) Max(1, 1) }; Line #1 := { Point(-0.7, -0.7) Point(0.7, -0.7) DebounceTime(0.10) Direction(1) }; Line #2 := { Point(-0.7, -0.7) Point(-0.7, 0.7) DebounceTime(0.10) Direction(1) }; Line #3 := { Point(-0.7, 0.7) Point(0.7, 0.7) DebounceTime(0.10) Direction(1) }; //@Task T:0 V:0 I:1 "Virtual Room" { Event#31:={CrossedLine#1}; Event#30:={CrossedLine#2}; Event#29:={CrossedLine#3}; external Counter#1 := { Event#31 Text("Linie 1:") TopLeft(4,4) }; external Counter#2 := { Event#30 Text("Linie 2:") TopLeft(4,14) }; external Counter#3 := { Event#29 Text("Linie 3:") TopLeft(4,24) }; Counter#32 := { Counter#1 + Counter#2}; external Counter#4 := { Counter#32 - Counter#3 Text("Virtual Room:") TopLeft(-0.9,-0.9) }; //@} |
|
//@Task T:0 V:0 I:1 "No yellow object" { ColorHistogram #1:= { HSV(60,100,100,20) HSV(60,100,60,20) HSV(60,100,30,20) Similarity(75) Outlier(55) }; external ObjectState #1 := not SimilarToColor #1; external Event #1 := OnSet ObjectState #1; //@} |
|
//Definition of task primitives Resolution:= { Min(-1, -1) Max(1, 1) }; Line #1 := { Point(-0.1, -0.8) Point(-0.1, 0.8) DebounceTime(0.10) Direction(1) }; //@Task T:0 V:0 I:1 "Count red objects" { ColorHistogram #1:= { HSV(0,100,100,20) HSV(0,100,60,20) HSV(0,100,30,20) Similarity(75) Outlier(55) }; Event#31:={CrossedLine#1 where SimilarToColor #1}; external Counter#1 := { Event#31 Text("Linie 1:") TopLeft (-0.9,-0.9) }; //@} |
|
//Definition of task primitives Resolution:= { Min(-1, -1) Max(1, 1) }; Field #1 := { Point(-0.7, -0.7) Point(0.7, -0.7) Point(0.7, 0.7) Point(-0.7, 0.7) DebounceTime(5.00) ObjectSet(FootPoint) }; //@Task T:0 V:0 I:1 "Debounce Size" { ObjectState#21 := ObjectSize within(5,500); ObjectState#22:=OnChange ObjectState#21 within (0,5); external ObjectState#1:=InsideField#1 and ObjectState#21 and !ObjectState#22; //@} |
|
Resolution:= { Min(-1, -1) Max(1, 1) }; //@Task T:0 V:0 I:1 "30 sec alarm" { external SimpleState#1:= Appeared within(0,30); //@} |
|