Skip to content

Introduction

GnosisEvent Processing Language (GnosisEPL) is a video event query language that allows users to query objects and relationships in continuous video streams. GnosisEPL leverages the strength of openCypher project and Knowledge Graphs to query video data effectively. The schema is easy to understand, learn and write. It combines the principles of standard data access languages to construct expressive and efficient queries.

GnosisEPL is a declarative language for describing visual Spatio-temporal patterns using SQL-like syntax. It allows users to select visual objects, apply spatial and temporal operations, filter using a condition and finally composing output in various formats. It also includes Quality of Service (QoS) metrics to further refine the results and the processing undertaken..

Query Specification

Schema

REGISTER QUERY [query name]  
OUTPUT [ANN\_IMAGE\_BBOX | ANN\_IMAGE\_QUERY\_OUTPUT | K\_GRAPH\_IMAGE | K\_GRAPH\_DICT]  
CONTENT Service(s)Name  
MATCH [openCypher query] {(p:PERSON)}  
WHERE [expression] {p.gender='male'}  
FROM [publisher id]  
WITHIN [TUMBLING\_COUNT\_WINDOW|TUMBLING\_TIME\_WINDOW | SLIDING\_COUNT\_WINDOW | SLIDING\_TIME\_WINDOW]  
RETURN [reference id list]

Detailed Schema with example

Query Statements Comments
REGISTER QUERY SomeQuery query name, unique for each sub
OUTPUT K_GRAPH_JSON any of (ANN_IMAGE_BBOX | ANN_IMAGE_QUERY_OUTPUT | K_GRAPH_IMAGE | K_GRAPH_JSON)
CONTENT ObjectDetection, ColorDetection, ObjectDistanceDetection Optional statement. List of Services, separated by comma
MATCH (p:person)-[r:close_to Valid Cypher query Match statement.
OPTIONAL MATCH ©-[:on_top_of]->(p:person) Valid Cypher optional MATCH statement.
WHERE c:car AND c.color = “blue” Valid Cypher WHERE statement.
FROM web_cam1, webcam2 publisher id separated by comma or “*” for all
WITHIN TUMBLING_COUNT_WINDOW(10) Any one of the available functions (with their respective arguments): (TUMBLING_COUNT_WINDOW|TUMBLING_TIME_WINDOW | SLIDING_COUNT_WINDOW | SLIDING_TIME_WINDOW)
WITH_QOS accuracy = “high”, latency = “low” List of QoS policies to be used by the query, separated by comma
RETURN p, r.distance, COUNT(b) as closeBuses, COUNT(x) as blueCars Valid Cypher return statement

Registering query name

  • While writing any GnosisEPL query,the query name identifier is used to distinguish different queries within the Gnosis UI. Please keep in mind that this field is not used by the backend node, rather Gnosis adds its unique identifier to each query. Later, the query name can be used to retrieve the output on the UI.
  • The GnosisEPL query name is alphanumeric and can also include special characters like underscore ( _ ) and hyphen( - ).

Examples

  • REGISTER QUERY jay_walking_event
  • REGISTER QUERY bike_chasing_a_car

Content Services

  • The required services need to be defined as a list separated by commas and space.

  • For example: CONTENT ObjectDetection, ColorDetection
    Here, the user mentions two services - ObjectDetection and ColorDetection to be executed in the same order along the pipeline.

  • Another possible way of defining the Content services is:
    CONTENT node\_type:car, node\_attribute:color, node\_attribute:sentiment, relation:left\_of,
    In this case, it would be for a query that asks for a car with a specific color, and that also asks for a relationship of the type "left_of", in an event that has a given type of sentiment. Internally GNOSIS would just check what are the available services that can extend the VEKG with the given node types, attributes and relations, and build a service function chain with the necessary operators. Later on, this can be omitted by the user in the query, and gathered by the system itself, since all of this should be possible to gather from the query information.

  • Currently, GNOSIS makes use of the following four services to serve the results:

    • COCOObject Detection:
      This service uses the TF model zoo, and the SSDImageNet framework to identify class labels on the objects. The labels are used from the COCO model framework which can detect upto 80 different classes.

    • PPEDetection:
      This service uses the tensorflow-based YOLOv3 architecture to serve its purpose. This service can detect whether the person is wearing a safety hard hat or not (labels: wearing_hat and not_wearing_hat).

    • PPEColorHatDetection:
      This service uses the tensorflow-based tiny YOLOv3 architecture. The purpose of this service is to identify the colour of the hat being worn by the worker. (labels: blue, yellow, white, red, none)

    • ColorDetection:
      This service is built on the OpenCV color detection filter. It can identify the presence of red, yellow, white colours within a given frame or bounding box.

Output Formats

GnosisEPL supports three output formats currently.

  • ANN_IMAGE_BBOX : Displays output as a stream of images encoded with Object and Relationships information. The result is an image annotated with the class label, and bounding box of the object(s)
  • ANN_IMAGE_QUERY_OUTPUT : Displays output as a stream of images encoded with Object and Relationships information. The result is an image annotated with the RETURN clause output (eg. Visitor Count: 2, this information embedded on the image)
  • K_GRAPH_IMAGE : Displays output as a Knowledge Graph image generated from Objects and Relationships running over the length of a source video.
  • K_GRAPH_JSON: Displays output as a Knowledge Graph JSON generated from Objects and Relationships running over the length of a source video.

Example :An object detection query that identifies objects of the type of PERSON and seeks LEFT relationships among them.

ANN_IMAGE_BBOX

  • Query :

    • REGISTER QUERY ObjectDetectionLEFT_OF_test
      OUTPUT ANN_IMAGE_BBOX
      CONTENT ObjectDetection
      MATCH (p1:Person {label:'PERSON'})\<-[SPATIAL:LEFT]-(p2:Person {label:'PERSON'})
      FROM file_walking.mp4
      WITHIN TUMBLING_COUNT_WINDOW(5)
      RETURN p1, p2
  • Output Format : PNG Image in base64.

ANN_IMAGE_QUERY_OUTPUT

  • Query :

    • REGISTER QUERY CountHardHatWorkers​
      OUTPUT ANN_IMAGE_BBOX, ANN_IMAGE_QUERY_OUTPUT​
      CONTENT PPEDetection, ColorDetection​
      MATCH (worker_hat:HAT)​
      WHERE worker_hat.color='WHITE' ​ FROM video.mp4​
      RETURN COUNT(visitor_hat) as VisitorCount
  • Output Format : PNG Image in base64.

K_GRAPH_IMAGE

  • Query :

    • REGISTER QUERY ObjectDetectionLEFT_OF_test
      OUTPUT K_GRAPH_IMAGE
      CONTENT ObjectDetection
      MATCH (p1:Person {label:'PERSON'})\<-[SPATIAL:LEFT]-(p2:Person {label:'PERSON'})
      FROM file_walking.mp4
      WITHIN TUMBLING_COUNT_WINDOW(5)
      RETURN p1, p2
  • Output Format : PNG Image in base64.

K_GRAPH_JSON

  • Query :

    • REGISTER QUERY ObjectDetectionLEFT_OF_test
      OUTPUT K_GRAPH_JSON
      CONTENT ObjectDetection
      MATCH (p1:Person {label:'PERSON'})\<-[SPATIAL:LEFT]-(p2:Person {label:'PERSON'})
      FROM file_walking.mp4
      WITHIN TUMBLING_COUNT_WINDOW(5)
      RETURN p1, p2
  • Output Format : JSON

Representing objects in GnosisEPL

Object Class

  • Objects are the data entities in your data stream. In our example, Person and Car are objects. Objects refer to a particular class and are written in CAPITAL letters. Classes themselves represent object labels.
  • To depict objects, we surround the node with parentheses, e.g. (:PERSON), (:CAR). Notice how the class appears in CAPITALS inside the small bracket.

Object Variable

  • Objects are designated by reference variables to reference them by that same name later in a query. The reference variable can be any letter (p:PERSON) or word (person:PERSON), usually written in lowercase. If the object is not relevant to your return results, you can specify an anonymous object using empty parentheses (:PERSON).

Object Properties

  • Object properties are name-value pairs that provide additional information about the object itself. One common practice is to use properties to describe a specific object class.
  • The name and value of the property go inside the curly braces within the parentheses of an object (p:PERSON {gender:'male'}).

Object Relationship

  • GnosisEPL supports two types of relationships: SPATIAL and TEMPORAL. Relationships help to evaluate Query Operators. Query Operators assess how objects are connected and related to each other. GnosisEPL has a list of query operators supported.
  • You can try to search for multiple relationships using a single query. Several relationships are connected by logical operators (OR | AND).
  • Relationships are represented using an arrow --> or <-- between two objects in a square bracket. Undirected relationships are represented with no arrow and just two dashes --. ←[SPATIAL:LEFT]--

Examples:

  • MATCH (p:PERSON {gender:'male'}) AND (c:CAR type:'sedan'})
  • MATCH (p1:PERSON {label:'Person'}) [SPATIAL:LEFT] - (p2:Person {label:Person})

More Info:

Adding predicates using WHERE clause

  • WHERE adds constraints to the patterns in a MATCH or OPTIONAL MATCH.
  • Note: In the case of multiple MATCH / OPTIONAL MATCH clauses, the predicate in WHERE is always a part of the patterns in the directly preceding MATCH / OPTIONAL MATCH.
  • WHERE supports boolean operators, String matching and filters on objects, attributes and relationships.

Boolean operators

  • Filter results based on boolean operators: AND, OR and NOT.
    MATCH (c:Car)
    WHERE NOT c.color = 'blue' AND (c.type = 'sedan' OR c.type = 'hatchback')
    RETURN c

Filter on object classes

  • Filter results based on a class type.
    MATCH (c)
    WHERE c:Car
    RETURN c.brand

Filter on object attributes

  • Filter results based on an object attribute.
    MATCH (t:Truck)
    WHERE t.multi_axle = true
    RETURN t

For String Matching and others operations

Windowing of events: Understanding Sliding and Tumbling Windows

  • Windows move continuous streaming data across the data pipeline by splitting the data into finite data chunks.
  • These data chunks make it efficient to perform pattern matching and evaluate query operators.
  • Window operation group messages together in a single window based on time or count.
  • Data windows hold incoming events before release is indicated by an expiry policy. Data windows are also a way of displaying what subset of events to evaluate.
  • You can define four types of windows in GnosisEPL.
    • TUMBLING_COUNT_WINDOW
    • TUMBLING_TIME_WINDOW
    • SLIDING_COUNT_WINDOW
    • SLIDING_TIME_WINDOW

Before we dive into the types, it is important to understand the concept of a time window and a count window and the difference between a tumbling and a sliding window.

  • Time Window:
    A time window is a moving window extending to the given time interval in the past. For example, a query as follows:

    select * Event#time(4 sec)
    
    would hold the events in the past four seconds in the data window. To sum up, this window is a moving time window which, based on system time, extends the given time interval into the past.

  • Count Window:
    Count windows buffer the stream of events until a threshold (number of events) is reached and then release them for processing. For example, a query as follows:

    select count(5) from Events output snapshot
    
    would buffer the number of events until 5 and then release them for output.

  • Sliding Window:
    A sliding window uses a slide lesser than the window size to traverse over the database. Let's say our database has 6 rows, and we take the window size to be 3- the sliding window would take the instances (1, 2 and 3) in the first case, sliding over (removing 1 and adding 4) to take the instances (2, 3 and 4) in the second case and similarly until 4 instances are used to traverse the whole database.

  • Tumbling Window:
    In contrast to a sliding window, the slide is equal to the window size for a tumbling window. For the example above, it would take only 2 instances for a tumbling window (1, 2, 3 and 4, 5, 6) to traverse the complete DB.

It's safe to say that now the concepts for the windows used in GnosisEPL should be easier to understand.

  • TUMBLING_COUNT_WINDOW
    A window which would buffer the number of events until a count is reached, and send that buffer for processing while sending the already processed one to be removed completely.

  • TUMBLING_TIME_WINDOW
    A window which would hold the number of past events for the time specified, and send that buffer for processing while sending the already processed one to be removed completely.

  • SLIDING_COUNT_WINDOW
    A window which would buffer the number of events until a count is reached, and send that buffer for processing while sending the top one event of the already processed to be removed completely. The next instance would contain the n-1 (n = number of events in a window) already processed events and one new event.

  • SLIDING_TIME_WINDOW
    A window which would hold the number of past events for the time specified, and send that buffer for processing while sending the top one event of the already processed to be removed completely. The next instance would contain the n-1 (n = number of events in a window) already processed events and one new event.

Return Statement

  • Return clause specifies the nodes to return as an output.
  • Use '*' symbol to get all nodes. It acts as a wildcard.
    • RETURN *
  • Use object references to indicate individual nodes.
    • RETURN a, b
    • Here, a and b must match one of the object references mentioned in MATCH clause.

Quality of Service Statement

Example of queries:

REGISTER QUERY some_query
OUTPUT K_GRAPH_DICT
MATCH {(p:PERSON)}
WHERE {p.gender=’male’}
FROM publisher2
WITHIN TUMBLING_COUNT_WINDOW(2)
WITH_QOS
   accuracy = [MIN | MEDIUM | MAX],
   energy_consumption = [MIN | MEDIUM | MAX],
   latency = [MIN | MEDIUM | MAX]
RETURN p
  • Used to define any set of user defined QoS dimensions policies, eg: accuracy, latency and energy consumption.
  • Other future QoS metrics should also be considered, but for now this considers only simple metrics in the form of KEY/Value notation. Example of possible future QoS: bandwidth, security_level (security can be seen as a dimension of QoS in distributed systems).
  • Any QoS metric not specified should be treated depending on the specific optimisation strategy used. Eg: if no accuracy is specified, then by default use the minimum accuracy that is possible for the system, and so on.
  • The values can be quantitative or qualitative. Eg: accuracy \< 0.8 for quantitative, or accuracy < "high" as a qualitative value.
  • For the qualitative values, it could be used fuzzy logic to transform the "human like" values (fuzzy) to classical quantitative values. Apart from the defuzzification, it can also be used for the fuzzyfication, which would establish what are the fuzzy sets that represent that classical value.
  • If QoS statement is optional, and the default behaviour for when it is not defined should be specified according to what the system is targeting in its optimizations (eg: energy consumption reduction, latency reduction, and others)

GNOSIS EPL SPATIOTEMPORAL EVENT OPERATORS

Query Operators are a part of Gnosis EPL that help determine relationships between objects. The operators can be spatial, temporal or logical depending on the user requirement. A more detailed description of the types is as follows:

Spatial Operators:

As the name suggests, these operators act/behave in the space continuum determining spatial relationship with the object at focus. The types of spatial operators used in GNOSIS are:

  • LEFT:
    The purpose of the operator is to determine if object 1 is to the left of object 2. For example, in the image first person is to the left of the person walking away from the camera, this is the kind of spatial relationship that GNOSIS expands and describes. This is the case for the images to follow as well, changing the type of relationship.

QUERY FORMAT:

MATCH (p1:person)-[SPATIAL:LEFT]>(p2:person)
This is telling the system to identify if the person is to the left of our object, which in this case is also a person, and the output image does exactly that.

  • RIGHT:
    The purpose of the operator is to determine if object 1 is to the right of object 2.

QUERY FORMAT:

MATCH (p1:person)-[SPATIAL:RIGHT]>(p2:person)
This is telling the system to identify if the person is to the right of our object, which in this case is also a person, and the output image does exactly that.

  • FRONT:
    The purpose of the operator is to determine if object 1 is ahead of object 2.

QUERY FORMAT:

MATCH (p1:person)-[SPATIAL:FRONT]>(p2:person)
This is telling the system to identify if the person is ahead of our object, which in this case is also a person, and the output image does exactly that.

  • BACK:
    The purpose of the operator is to determine if object 1 is behind object 2.

QUERY FORMAT:

MATCH (p1:person)-[SPATIAL:BACK]>(p2:person)
This is telling the system to identify if the person is behind our object, which in this case is also a person, and the output image does exactly that.

  • OVERLAP_TOP:
    The purpose of the operator is to determine if there is an overlap of object 1 with object 2. The aim is fulfilled by determining the percentage of overlap between the bounding boxes of the two objects. GNOSIS treats this as the object's area and determines the overlap.

QUERY FORMAT:

MATCH (worker:Person)<-[SPATIAL:OVERLAP\_TOP]-(worker\_hat:Hat {color:'WHITE'})
This is telling the system to identify if the person (our object) has a white coloured hat (another object) on top of it.

  • INSIDE: <WIP>
    The purpose of this operator is to determine whether object 1 is in proximity of or inside object 2. This is done by comparing bounding boxes of the two objects, and if there is an overlap between the two, we can say that GNOSIS would determine this operator to be true.

QUERY FORMAT:

MATCH (p1:person)-[INSIDE]>(unsafe_zone)
This is telling the system to identify if the person is inside an unsafe zone, which could be the cause of possible harm to him.

TEMPORAL Operators:

As the name suggests, these operators act/behave in the time continuum determining temporal relationship with the object at focus (eg. before, after etc).

AGGREGATE Operators:

These operators are more like SQL where they cater to the logic behind the keyword. GNOSIS makes use of the cypher-like operators and are as follows:

  • COUNT:
    This operator counts the number of qualified instances as per the user requirements.

    RETURN COUNT(worker_hat) as WorkerCount
    
    Here the worker_hat variable is instanced, then counted and returned as the number of workers in the workplace (assuming every worker is wearing a hat).

  • DISTINCT:
    This operator returns distinct qualified instances as per the user requirements.

    RETURN COUNT(DISTINCT worker_hat)
    
    Here the worker_hat variable is instanced, then different individuals are realised using DISTINCT, then counted and returned as the number of different workers in the workplace.

LOGICAL Operators:

These operators are more like SQL where they cater to the logic behind the keyword. GNOSIS makes use of the cypher-like operators and are as follows:

  • AND: This operator acts like the logical AND, returning TRUE only and only if both the conditions are satisfied.

    MATCH (worker:Person)<-[SPATIAL:OVERLAP_TOP]->(worker_hat:Hat) 
    WHERE worker_hat.color='WHITE' AND worker_hat.color='YELLOW' 
    RETURN COUNT(DISTINCT worker_hat)
    
    Here the query matches the given MATCH clause with hat color as WHITE and YELLOW. The data must have both hat colors.

  • OR:
    This operator acts like the logical OR, returning TRUE if either one of the two conditions is satisfied.

    MATCH (worker:Person)<-[SPATIAL:OVERLAP_TOP]->(worker_hat:Hat) 
    WHERE worker_hat.color='WHITE' OR worker_hat.color='YELLOW' 
    RETURN COUNT(DISTINCT worker_hat)
    
    Here the query matches the given MATCH clause with hat color as WHITE OR YELLOW. The data must have either of the two hat colors.

GNOSIS EPL Examples

This section aims to cover the use cases that have been worked upon and are well supported by GNOSIS. The queries would give a good understanding of the operators, schema and everything related in a more practical and real-time scenario.

Use Case: Occupational Health and Safety

PPE Compliance in Construction/Manufacturing Site:

PPE Hard Hat Compliance:

  • Detecting number of workers wearing a hard hat:
    QUERY:

REGISTER QUERY CountHardHatWorkers  
OUTPUT ANN_IMAGE_BBOX, ANN_IMAGE_QUERY_OUTPUT  
CONTENT PPEDetection  
MATCH (worker_hat:HAT)  
FROM video.mp4  
RETURN  
COUNT(worker_hat) as WorkerCount
Operators Used: COUNT

Here, what we expect from the system, is to give us an annotated image with a bounding box(es) for the qualified objects/instances. We use the PPEDetection service here. The MATCH clause uses the hat object to identify the worker in the workplace and a worker count is returned using the logical operator COUNT. This is a simple query with high efficiency for results and solves the purpose for counting the number of workers in the workplace.

  • Detecting number of workers not wearing a hard hat:
    QUERY:
    REGISTER QUERY CountNonHardHatWorkers  
    OUTPUT ANN_IMAGE_BBOX, ANN_IMAGE_QUERY_OUTPUT  
    CONTENT PPEDetection  
    MATCH (non_worker:NOT_HAT)  
    FROM video.mp4
    RETURN  
    COUNT(non_worker) as NonWorkerCount
    

Operators Used: COUNT

Here, what we expect from the system, is to give us an annotated image with a bounding box(es) for the qualified objects/instances. We use the PPEDetection service here. The MATCH clause uses the not_hat class to identify the worker in the workplace without a hat; and a worker count violating the compliance is returned using the logical operator COUNT. The purpose is to count the number of workers not wearing a hat in the workplace.

  • Detecting number of workers and visitors using the colour of the hard hat: QUERY:
    REGISTER QUERY CountHardHatWorkerAndVisitors  
    OUTPUT ANN_IMAGE_BBOX, ANN_IMAGE_QUERY_OUTPUT  
    CONTENT PPEDetection, ColorDetection  
    MATCH (worker_hat:HAT {color:’YELLOW’}) OR (visitor_hat:HAT {color:’WHITE’})
    FROM video.mp4  
    RETURN  
    COUNT(DISTINCT worker_hat) as WorkerCount, COUNT(DISTINCT visitor_hat) as VisitorCount  
    

Operators Used: COUNT, DISTINCT

Here, what we expect from the system, is to give us an annotated image with a bounding box(es) for the qualified objects/instances and the query output on the image as well. We use the PPEDetection and ColorDetection service here, as colour would be the metric of isolation of the two. The MATCH clause uses the hat class to identify a person in the workplace. The condition on the MATCH clause inputs a simple logic into the query that the person is wearing a white or yellow hat. The purpose is to differentiate between the two which is done in the RETURN statement, where the count of distinct persons wearing hats are returned as Visitors while those wearing a yellow hat are returned as Workers.

  • Detecting hard hat compliance:
    QUERY:
    REGISTER QUERY HardHatCompliance  
    OUTPUT ANN_IMAGE_BBOX, ANN_IMAGE_QUERY_OUTPUT  
    CONTENT PPEDetection  
    MATCH (worker_hat:HAT) OR (non_worker_hat:NOT_HAT)  
    FROM video.mp4  
    RETURN  
    COUNT(DISTINCT worker_hat)>0 AND COUNT(DISTINCT non_worker_hat)=0 as ComplianceStatus
    

Operators Used: COUNT, AND

Here, what we expect from the system, is to give us an annotated image with a bounding box(es) for the qualified objects/instances and the query output on the image as well. We use the PPEDetection service here. The MATCH clause uses the hat and not_hat class to identify a person wearing or not wearing a hat in the workplace. The RETURN statement uses a simple logic that if the number of persons not wearing a hat are zero while those wearing a hat greater than zero is true, the compliance status is achieved and a boolean is returned stating the same.

  • Detecting workers based on colour of Hard Hats:
    QUERY:
    REGISTER QUERY CountWorkerVisitorCompliance  
    OUTPUT ANN_IMAGE_BBOX, ANN_IMAGE_QUERY_OUTPUT  
    CONTENT ObjectDetection, PPEDetection, ColorDetection  
    MATCH (worker:Person)<-[SPATIAL:OVERLAP_TOP]-(worker_hat:Hat {color:'YELLOW'})  
    WHERE OVERLAP_TOP=60%  
    FROM video.mp4  
    RETURN  
    COUNT(DISTINCT SPATIAL) as WorkerCount
    
    Operators Used: COUNT, DISTINCT, OVERLAP_TOP

Here, what we expect from the system, is to give us an annotated image with a bounding box(es) for the qualified objects/instances and the query output on the image as well. We use the PPEDetection, ObjectDetection and ColorDetection services here, as colour is the basis of differentiation. The MATCH clause identifies two objects- Hat (of colour yellow) and the person and uses the OVERLAP_TOP operator to identify the compliance. The threshold of the compliance is set to be 60% such that if the bounding box of the two overlap by 60% or more, we can say that the person is wearing a hat. The RETURN statement counts the distinct number and returns the worker count.

  • Detecting visitors based on colour of Hard Hats:
    QUERY:
    REGISTER QUERY CountWorkerVisitorCompliance  
    OUTPUT ANN\_IMAGE_BBOX, ANN_IMAGE_QUERY_OUTPUT  
    CONTENT ObjectDetection, PPEDetection, ColorDetection  
    MATCH (worker:Person)<-[SPATIAL:OVERLAP_TOP]->;(worker_hat:Hat {color:'WHITE'})  
    WHERE OVERLAP_TOP=60%  
    FROM video.mp4  
    RETURN  
    COUNT(DISTINCT SPATIAL) as VisitorCount
    
    Operators Used: COUNT, DISTINCT, OVERLAP_TOP

Here, what we expect from the system, is to give us an annotated image with a bounding box(es) for the qualified objects/instances and the query output on the image as well. We use the PPEDetection, ObjectDetection and ColorDetection services here, as colour is the basis of differentiation. The MATCH clause identifies two objects- Hat (of colour white) and the person and uses the OVERLAP_TOP operator to identify the compliance. The threshold of the compliance is set to be 60% such that if the bounding box of the two overlap by 60% or more, we can say that the person is wearing a hat. The RETURN statement counts the distinct number and returns the visitor count. This query has a similar basis to the previous one.


Last update: April 30, 2021 12:43:18