Instantly share code, notes, and snippets.

# vmonaco/segment_motion.py Created Dec 7, 2015

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) # 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)
Owner Author

### vmonaco commented Dec 7, 2015

 Gray areas indicate detected motion.