Created
December 7, 2015 19:57
-
-
Save vmonaco/d90d596dc0ca49f42f78 to your computer and use it in GitHub Desktop.
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[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]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Gray areas indicate detected motion.
Example using accelerometer:
Example using gyroscope: