Presence detection human only#

This presence detector was generated from Presence detection (sparse). The purpose of this version of presence detector is to remove false detections created from non-human moving objects such as fans, plants, curtains and other possible objects in a small room. This presence detector works by comparing the fast motion score and slow motion score. Our investigation shows that the human creates high spikes in both fast and slow motion score, while moving objects create high spikes in slow motion score only. The key concepts for this presence detector are:

  • Comparing the fast and slow motion score to individually set thresholds

  • Implementation of adaptive threshold using fast motion guard interval

  • Implementation of fast motion outlier detection for quiet room (e.g. meeting room)

Slow motion and fast motion#

Below is an example of the detections of both fast and slow motions. It is measured in a room with size of approximately 3 x 3 x 3 m. The following events are:

  1. 0-80 seconds is empty room

  2. 80-100 seconds is people coming, installing and turning on a fan

  3. 100-250 seconds is empty room with a fan turned on

../../../_images/presence_human_only_1.png

Figure 37 A measurement with multiple cases of human and fan presence#

The Figure 37 can not be seen directly in exploration tool GUI, but was used in the algorithm development. From this we conclude:

  • The inter/slow motion is measuring human presence from, e.g., breathing

  • The intra/fast motion is measuring bigger movements from the human body

Fast motion score, \(s_\text{fast}(f)\), and slow motion score, \(s_\text{slow}(f)\), are calculated from the \(\bar{s}_\text{fast}(f, d)\) and \(\bar{s}_\text{slow}(f, d)\) by taking the maximum value over the distances. The \(\bar{s}_\text{fast}(f, d)\) that is \(\bar{s}_\text{intra}(f, d)\) and the \(\bar{s}_\text{slow}(f, d)\) that is \(\bar{s}_\text{inter}(f, d)\) are processed from the Presence detection (sparse) processor. The motion scores are then compared to fast motion threshold, \(v_f\), and slow motion threshold, \(v_s\), to obtain fast motion detection, \(p_f\), and slow motion detection, \(p_s\). Lastly, the decision of presence detected, \(p\), is defined as either fast motion detection or slow motion detection.

\[s_\text{fast}(f) = \max_d(\bar{s}_\text{fast}(f, d))\]
\[s_\text{slow}(f) = \max_d(\bar{s}_\text{slow}(f, d))\]
\[p_f = s_\text{fast} > v_f\]
\[p_s = s_\text{slow} > v_s\]
\[p = p_f \text{ or } p_s\]

Adaptive threshold#

Adaptive threshold is one of the configurations to remove false detections created by fans, plants, and curtains. As mentioned before, those objects creates mainly slow motions. The adaptive threshold works by recording the maximum value of slow motion score for each distance during a recording time. We use these recorded values as a new threshold for each distance with the expectation that the recorded slow motion scores are the highest slow motion values created by the non-human objects. It is expected not to have fast motion detection during the recording time. For this implementation to work, there are three main timelines as shown in the Figure 38. This picture can not be seen directly in exploration tool GUI, but was used in the algorithm development.

  1. A person was inside of the room or inside the sensor coverage. The fluctuations of slow motion score will not be recorded because of the fast motion detection. The recording time will start when there is no fast motion.

  2. The room is empty, but slow motion score has not settled due to the low pass filtering in the presence detector. The slow motion score will not be recorded. This time window, \(w_h\), is dependent on the the slow_motion_deviation_time_const, \(\tau\).

  3. The last time window, \(w_\text{cal}\), is the actual recording step of the slow motion score, which later will be set as a new threshold. The B and C time windows are combined in the \(w_g\), controlled by the fast_guard_s. We have the following:

\[w_h = 5 \cdot \tau\]
\[w_\text{cal} = w_g - w_h\]
../../../_images/presence_human_only_2.png

Figure 38 Implementation of adaptive_threshold#

The non-human object, can in some cases create motion that will be detected as presence. The false detections, such as false negative and false positive, marked with red circles on Figure 39, are caused by different results from slow motion detection and fast motion detection.

By activating the adaptive threshold, it will automatically change the threshold over distances to a threshold value that is higher than the measured slow motion detection. The Figure 39 on the third plot represents the threshold for the case of plant in the room after fast motion guard periods completed.

../../../_images/presence_human_only_3.png

Figure 39 UI appearance#

After the fast guard window, the slow motion threshold will not have equal values for all distances any longer. The slow motion detection, \(p_s\), is then redefined as comparing the depthwise slow motion score, \(\bar{s}_\text{slow}(f, d)\), to the recorded depthwise slow motion threshold \(\bar{v}_s(d)\).

\[p_s = \bar{s}_\text{slow}(f, d) > \bar{v}_s(d)\]

Fast motion outlier detection#

In fast motion detection, humans will be detected if they create enough fast motion. If a person is sitting still, it will create a very low spike. Due to the consistency of the fast motion score, this low spike can be detected in the fast motion detection even though it is not above the threshold value. The fast motion outliers detection has the purpose of detecting this relatively short and weak fast motion. It records previous frames of fast motion score, \(s_\text{fast}(f)\). The recorded values are then sorted from least to greatest, \(\bar{u}\). The \(1^{st}\) quartile and \(3^{rd}\) quartile are calculated with percentile based formula. With \(n_s\) being the number of recorded values we have:

\[s_\text{fast}(f) = \max_d(\bar{s}_\text{fast}(f, d))\]
\[\bar{u} = [s_\text{fast}(f_{0}), s_\text{fast}(f_{1}), ...] \text{, such that } s_\text{fast}(f_{i}) < s_\text{fast}(f_{i+1})\]
\[Q_1 = \frac{n_s + 1}{100} \cdot 25 \cdot \bar{u}\]
\[Q_3 = \frac{n_s + 1}{100} \cdot 75 \cdot \bar{u}\]

The interquartile range, \(IQR\), for fast motion score is calculated to determine the boundaries for the outlier detection. Based on our investigation, the human creates an \(IQR\) value above 0.15, hence, the IQR is defined to never exceed this value. The lower boundary, \(L_b\), and the upper boundary, \(U_b\), are then calculated from the \(IQR\) and the \(Q_\text{factor}\). The \(Q_\text{factor}\) adjusts the boundaries and sets the sensitivity in the outlier detection. The more fluctuative fast motion score in an empty room without human is, the higher the \(Q_\text{factor}\) should be. In our investigation, the optimal value of \(Q_\text{factor}\) is 3 to differentiate between a human and other objects. Finally, the fast motion detection, \(p_f\), will also be defined as the fast motion score being outside the boundaries.

\[\begin{split}IQR = \begin{cases} Q_3 - Q_1 & \text{if } Q_3 - Q_1 <0.15 \\ 0.15 & \text{otherwise} \\ \end{cases}\end{split}\]
\[L_b = Q_1 - Q_\text{factor} \cdot IQR\]
\[U_b = Q_3 + Q_\text{factor} \cdot IQR\]
\[\begin{split}p_f = \begin{cases} s_\text{fast} > U_b \text{ or } s_\text{fast} < L_b & \text{if } s_\text{fast} <= v_f \\ s_\text{fast} > v_f & \text{otherwise}\\ \end{cases}\end{split}\]

Graphical overview#

digraph { pad=0.1 ranksep=0.3 nodesep=0.3 bgcolor="#ffffff00" fontname=sans fontsize=12 style=rounded node [fontname=sans, fontsize=12, shape=record, style=rounded] subgraph cluster { style=invis subgraph cluster_fast { label="Fast Motion \nDetection" style=rounded fast_motion_score -> max_over_distances_fast -> compare_against_threshold_fast -> fast_motion_detection fast_motion_score -> outlier_detection outlier_detection -> record_fast_motion_score [ label = "Y" ]; record_fast_motion_score -> {calculate_lower_boundary, calculate_upper_boundary} calculate_upper_boundary -> compare_against_upper_boundary_fast -> fast_motion_detection calculate_lower_boundary -> compare_against_lower_boundary_fast -> fast_motion_detection } subgraph cluster_slow { label="Slow Motion \nDetection" style=rounded slow_motion_score -> adaptive_threshold adaptive_threshold -> compare_against_recorded_threshold [ label = "N" ]; adaptive_threshold -> record_slow_motion_score [ label = "Y" ]; record_slow_motion_score -> frame_index frame_index -> compare_against_recorded_threshold [ label = "N" ]; frame_index -> set_recorded_threshold [ label = "Y" ]; set_recorded_threshold -> compare_against_recorded_threshold compare_against_recorded_threshold -> slow_motion_detection } } in -> {fast_motion_score, slow_motion_score} fast_motion_detection -> out slow_motion_detection -> out in [shape=Mdiamond, label="Presence detection (sparse)\nresult"] { rank=same; fast_motion_detection; slow_motion_detection; } fast_motion_score [label="Fast motion score"] slow_motion_score [label="Slow motion score"] max_over_distances_fast [label="Max over distances"] outlier_detection [shape = diamond; label="Outlier detection"] adaptive_threshold [shape = diamond; label="Adaptive threshold"] frame_index [shape = diamond; label="Recording time \nfinished"] compare_against_threshold_fast [label="Compare against threshold"] compare_against_upper_boundary_fast [label="Compare against \nupper boundary"] compare_against_lower_boundary_fast [label="Compare against \nlower boundary"] compare_against_recorded_threshold [label="Compare against \ndepthwise threshold"] set_recorded_threshold [label="Set recorded threshold as \na new slow threshold"] record_fast_motion_score [label="Record fast motion \nscore"] record_slow_motion_score [label="Record slow motion \nscore"] calculate_upper_boundary [label="Calculate upper \nboundary"] calculate_lower_boundary [label="Calculate lower \nboundary"] fast_motion_detection [label="Fast motion detection"] slow_motion_detection [label="Slow motion detection"] out [shape=Msquare, label="Output"] }

Configuration parameters#

class acconeer.exptool.a111.algo.presence_detect_human_only.ProcessingConfiguration#
slow_motion_threshold#

Level at which the slow motion detection is considered as “Slow motion”.

Type: float
Default value: 2
slow_motion_hf_cutoff#

Cutoff frequency of the low pass filter for the fast filtered sweep mean. No filtering is applied if the cutoff is set over half the frame rate (Nyquist limit).

Type: float
Unit: Hz
Default value: 20.0
slow_motion_lf_cutoff#

Cutoff frequency of the low pass filter for the slow filtered sweep mean.

Type: float
Unit: Hz
Default value: 0.2
slow_motion_deviation_time_const#

Time constant of the low pass filter for the (slow-motion) deviation between fast and slow.

Type: float
Unit: s
Default value: 3
fast_motion_threshold#

Level at which the fast motion detection is considered as “Fast motion”.

Type: float
Default value: 1.4
fast_motion_time_const#

Time constant for the fast motion part.

Type: float
Unit: s
Default value: 0.5
fast_motion_outlier#

Fast motion detection includes outlier detection to optimize detection in (i.e.) meeting room.

Type: bool
Default value: False
num_removed_pc#

Sets the number of principal components removed in the PCA based noise reduction. Filters out static reflections. Setting to 0 (default) disables the PCA based noise reduction completely.

Type: int
Default value: 0
show_data#

Show the plot of the current data frame along with the fast and slow filtered mean sweep (used in the slow-motion part).

Type: bool
Default value: True
show_slow#

Show the slow motion plot.

Type: bool
Default value: True
show_fast#

Show the fast motion plot.

Type: bool
Default value: True
adaptive_threshold#

Changes the threshold array based on the slow and fast motion processing

Type: bool
Default value: True
show_sectors#
Type: bool
Default value: False
fast_guard_s#

Recording time/period in seconds where there should be no fast motion in the recording period. It records the maximum slow motion threshold as a new threshold.

Type: float
Default value: 160
history_length_s#
Type: float
Unit: s
Default value: 5