{{ message }}

Instantly share code, notes, and snippets.

# vmonaco/segment_motion.py

Created Dec 7, 2015
Segment motion using a 2-state Gaussian HMM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 """ 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) # 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, g.iloc[-1], facecolor='k', alpha=0.2, linewidth=0) plt.legend(lines, ('X', 'Y', 'Z')) plt.show() motion.to_csv(sys.argv)

### vmonaco commented Dec 7, 2015

Gray areas indicate detected motion.