robotology / assistive-rehab

Assistive and Rehabilitative Robotics
https://robotology.github.io/assistive-rehab/doc/mkdocs/site
BSD 3-Clause "New" or "Revised" License
21 stars 11 forks source link

Improve the peak finding algorithm for gait estimation #340

Closed mfussi66 closed 1 year ago

mfussi66 commented 1 year ago

The peak finding algorithm is used by the motionAnalyzer module to detect in real time the number of steps that the patient does while walking. This information is also used to estimate cadence and speed of the subject. The algorithm is also used in the reporting Python notebooks, for offline processing of the skeleton data.

The Python notebook uses a Scipy function, while the motionAnalyzer uses a handcrafted one. Both implementations are quite sensitive to noise profile and configuration parameters (e.g. peak threshold). To improve robustness of the procedure we could use better techniques, that can be tracked in this issue.

mfussi66 commented 1 year ago

Continuous wavelet transforms

Peak-finding through CWT is a particular application of wavelet-based convolution. The wavelet is scaled in width multiple times and the local maxima for each scaled convolution are linked to each other. This is a reference paper: https://academic.oup.com/bioinformatics/article/22/17/2059/274284?login=false It's implementation is included in Scipy and can be tested.

pattacini commented 1 year ago

Another possibility, less advanced but easier to tune, is to resort to an SG filter as in https://www.mathworks.com/matlabcentral/answers/696995-find-peaks-valleys-of-a-noisy-signal.

mfussi66 commented 1 year ago

Scipy already provides the SG filter, so it was easy to implement.

At the moment I used the following set of computations:

  1. compute difference between ankles
  2. apply SG filter to difference
  3. compute norm2 to get distance between ankles
  4. remove outliers outside 3 standard deviations using zscore, replace with 0.0
  5. use the standard find_peaks function

The parameters are:

Here is a usage example with the small dataset used previously. The cliff at ~45sec is somewhat of an outlier, and the two peaks to the side should only by one. short_distance

Here is a bigger dataset with less forgiving data long_dataset

The filter seems promising, however it needs to be verified if the peaks are actual steps. To do so, I will see if I can exhume a script posted in the previous issues that would reconstruct the skeleton from keypoints.

pattacini commented 1 year ago

Really promising! I reckon we can open a PR to integrate this latest tidbit.

mfussi66 commented 1 year ago

Pr here! https://github.com/robotology/assistive-rehab/pull/342