Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Segment motion using a 2-state Gaussian HMM
"""
Segment an acceleration or gyroscopic CSV file into motion/non-motion segments
using a 2-state HMM and Savitzky–Golay filter as preprocessing
"""
import sys
import pandas as pd
import matplotlib.pyplot as plt
from hmmlearn.hmm import GaussianHMM
from scipy.signal import savgol_filter
WINDOW_LENGTH = 15 # Must be odd
POLY_DEGREE = 2
def segment(x, y):
# use a 2-state HMM to separate motion/non-motion states
hmm = GaussianHMM(n_components=2)
hmm.fit([y])
states = hmm.predict(y)
# the motion state is the one with the max mean, assuming y is some type of
# measure of motion (acceleration, velocity, gyroscope, etc.)
motion_state = hmm.means_.argmax()
return pd.Series(states == motion_state)
if __name__ == '__main__':
if len(sys.argv) != 3:
print('Usage: $ python segment_motion.py [input] [output]')
sys.exit(1)
df = pd.read_csv(sys.argv[1])
# mean absolute acceleration from 3 axes
y = df[['X_value', 'Y_value', 'Z_value']].abs().mean(axis=1)
# play the filter params or try using a different filter
y = savgol_filter(y, WINDOW_LENGTH, POLY_DEGREE)
# motion is a Series of booleans, True where there is motion
motion = segment(df['time'], y[:, None])
lines = plt.plot(df['time'], df[['X_value', 'Y_value', 'Z_value']])
# gray spans indicate motion
for _, g in df['time'][motion].groupby(motion.diff()[motion].cumsum()):
plt.axvspan(g.iloc[0], g.iloc[-1], facecolor='k', alpha=0.2, linewidth=0)
plt.legend(lines, ('X', 'Y', 'Z'))
plt.show()
motion.to_csv(sys.argv[2])
@vmonaco

This comment has been minimized.

Copy link
Owner Author

vmonaco commented Dec 7, 2015

Gray areas indicate detected motion.

Example using accelerometer:
gco_acc_events

Example using gyroscope:
gco_gyr_events

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.