├── util ├── __init__.py ├── util.pyc ├── __init__.pyc ├── __pycache__ │ ├── util.cpython-34.pyc │ └── __init__.cpython-34.pyc └── util.py ├── screenshots ├── freq.png ├── trace.png └── filter_time_domain.png ├── README.md └── acc.py /util/__init__.py: -------------------------------------------------------------------------------- 1 | from .util import* 2 | -------------------------------------------------------------------------------- /util/util.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KChen89/Accelerometer-Filtering/HEAD/util/util.pyc -------------------------------------------------------------------------------- /util/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KChen89/Accelerometer-Filtering/HEAD/util/__init__.pyc -------------------------------------------------------------------------------- /screenshots/freq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KChen89/Accelerometer-Filtering/HEAD/screenshots/freq.png -------------------------------------------------------------------------------- /screenshots/trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KChen89/Accelerometer-Filtering/HEAD/screenshots/trace.png -------------------------------------------------------------------------------- /screenshots/filter_time_domain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KChen89/Accelerometer-Filtering/HEAD/screenshots/filter_time_domain.png -------------------------------------------------------------------------------- /util/__pycache__/util.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KChen89/Accelerometer-Filtering/HEAD/util/__pycache__/util.cpython-34.pyc -------------------------------------------------------------------------------- /util/__pycache__/__init__.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KChen89/Accelerometer-Filtering/HEAD/util/__pycache__/__init__.cpython-34.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Accelerometer data filtering 2 | Filter 3D accelerometer data [1] with median and low pass filter. Median filter generally remove big spikes. But, high frequency noise exists at very low amplitude. Low pass filter only preserves low frequency which creates undesirable distortions. Combing median and low pass filter generally recovers a better trace (since there is no ground truth signal to verify which one is better, just follow orignal data description [1] and verify with eyes).
3 | ![time domain](screenshots/filter_time_domain.png) 4 | Time domain comparsion. 5 | ![3d trace](screenshots/trace.png) 6 | Accelerometer data 3D trace. 7 | ### Dependencies 8 | - Numpy 9 | - Scipy 10 | - Matplotlib 11 | 12 | :question: However, according the original data source description [1], the above 3D trace is suppose to be the displacement which is the integration of integration of accelerometer. When I integrated the data twice, it does not show a meaningful result. :confused: 13 | 14 | #### More 15 | - [x] filter data to create a clear trace 16 | - [ ] figure out the confusion. 17 | 18 | ### Reference 19 | [1] https://www.shimmersensing.com/support/sample-data/ 20 | -------------------------------------------------------------------------------- /acc.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 3D accelerometer filtering with median and low pass filter 3 | @author: Kemeng Chen 4 | ''' 5 | import os 6 | import sys 7 | import numpy as np 8 | import matplotlib.pyplot as plt 9 | from util import* 10 | 11 | def test_data(file_name): 12 | cur_dir=os.getcwd() 13 | fs=512 14 | cutoff=10 15 | file_path=os.path.join(cur_dir, 'data', file_name) 16 | data=read_data(file_path, [1,2,3]) 17 | plot_lines(data, fs, 'Raw data') 18 | fft_plot(data, fs, 'Raw data') 19 | median_data=median_filter(data, 155) 20 | lpf_data=freq_filter(data, 155, cutoff/fs) 21 | comb_data=freq_filter(median_data, 155, cutoff/fs) 22 | plot_lines(median_data, fs, 'median filter') 23 | plot_lines(lpf_data, fs, 'low pass filter') 24 | plot_lines(comb_data, fs, 'median+low pass filter') 25 | fft_plot(lpf_data, fs, 'low pass filter') 26 | fft_plot(median_data, fs, 'median filter') 27 | fft_plot(comb_data, fs, 'median+low pass filter') 28 | plot3D(data, 'raw data') 29 | plot3D(median_data, 'median filter') 30 | plot3D(lpf_data, 'low pass filter') 31 | plot3D(comb_data, 'median+low pass filter') 32 | plt.show() 33 | 34 | if __name__ == '__main__': 35 | if len(sys.argv)<2: 36 | raise ValueError('No file name specified') 37 | test_data(sys.argv[1]) -------------------------------------------------------------------------------- /util/util.py: -------------------------------------------------------------------------------- 1 | ''' 2 | utility function to read data, integration, and plot 3 | @author: Kemeng Chen 4 | ''' 5 | 6 | import os 7 | import sys 8 | import numpy as np 9 | import math 10 | import matplotlib.pyplot as plt 11 | from scipy.fftpack import fft 12 | from scipy import signal 13 | from mpl_toolkits.mplot3d import Axes3D 14 | 15 | def read_data(file_path, columns): 16 | ''' 17 | read files according to file_path and columns 18 | args: 19 | file_path, columns (list) 20 | return: 21 | data (numpy array) 22 | ''' 23 | if not os.path.isfile(file_path): 24 | raise AssertionError(file_path, 'not found') 25 | mode='r' 26 | with open (file_path, mode) as f: 27 | lines=f.readlines() 28 | num_rows=len(lines) 29 | print(str(num_rows), ' rows') 30 | num_cols=len(columns) 31 | data=np.zeros([num_rows, num_cols]) 32 | for indice, line in enumerate(lines[3:]): 33 | row=line.rstrip().split('\t') 34 | # print(row) 35 | for ii, i in enumerate(columns): 36 | data[indice,ii]=row[i] 37 | # data[:,2]-=10 38 | # for i in range(3): 39 | # data[:,i]=calibration(data[:,i]) 40 | f.close() 41 | return data 42 | 43 | def median_filter(data, f_size): 44 | lgth, num_signal=data.shape 45 | f_data=np.zeros([lgth, num_signal]) 46 | for i in range(num_signal): 47 | f_data[:,i]=signal.medfilt(data[:,i], f_size) 48 | return f_data 49 | 50 | def freq_filter(data, f_size, cutoff): 51 | lgth, num_signal=data.shape 52 | f_data=np.zeros([lgth, num_signal]) 53 | lpf=signal.firwin(f_size, cutoff, window='hamming') 54 | for i in range(num_signal): 55 | f_data[:,i]=signal.convolve(data[:,i], lpf, mode='same') 56 | return f_data 57 | 58 | def fft_plot(data, fs, title): 59 | lgth, num_signal=data.shape 60 | fqy=np.zeros([lgth,num_signal]) 61 | fqy[:,0]=np.abs(fft(data[:,0])) 62 | fqy[:,1]=np.abs(fft(data[:,1])) 63 | fqy[:,2]=np.abs(fft(data[:,2])) 64 | index=np.arange(int(lgth/2))/(int(lgth/2)/(fs/2)) 65 | fig, ax=plt.subplots() 66 | labels=['x','y','z'] 67 | color_map=['r', 'g', 'b'] 68 | for i in range(3): 69 | ax.plot(index, fqy[0:int(lgth/2),i], color_map[i], label=labels[i]) 70 | ax.set_xlim([0, fs/2]) 71 | ax.set_xlabel('Hz') 72 | ax.set_title('Frequency spectrum: '+title) 73 | ax.legend() 74 | 75 | def plot_lines(data, fs, title): 76 | num_rows, num_cols=data.shape 77 | if num_cols!=3: 78 | raise ValueError('Not 3D data') 79 | fig, ax=plt.subplots() 80 | labels=['x','y','z'] 81 | color_map=['r', 'g', 'b'] 82 | index=np.arange(num_rows)/fs 83 | for i in range(num_cols): 84 | ax.plot(index, data[:,i], color_map[i], label=labels[i]) 85 | ax.set_xlim([0,num_rows/fs]) 86 | ax.set_xlabel('Time [sec]') 87 | ax.set_title('Time domain: '+title) 88 | ax.legend() 89 | 90 | def acc_integration(data): 91 | num_rows, num_cols=data.shape 92 | int_data=np.zeros(data.shape) 93 | for i in range(num_cols): 94 | int_data[:,i]=TZ_integration(data[:,i]) 95 | return int_data 96 | 97 | def plot3D(data, title): 98 | fig=plt.figure() 99 | ax=fig.add_subplot(111, projection='3d') 100 | ax.plot(xs=data[:,0], ys=data[:,1], zs=data[:,2], zdir='z') 101 | ax.set_title(title) 102 | 103 | def calibration(signal): 104 | inc_eng=np.sum(np.clip(signal, a_min=0, a_max=None)) 105 | der_eng=-1*np.sum(np.clip(signal, a_max=0, a_min=None)) 106 | if inc_eng==0 or der_eng==0: 107 | raise ValueError('Calibration rule does NOT hold') 108 | 109 | if inc_eng>der_eng: 110 | beta_p=1 111 | beta_n=inc_eng/der_eng 112 | c_signal=(beta_n-1)*np.clip(signal, a_max=0, a_min=None)+signal 113 | elif der_eng>inc_eng: 114 | beta_n=1 115 | beta_p=der_eng/inc_eng 116 | c_signal=(beta_p-1)*np.clip(signal, a_min=0, a_max=None)+signal 117 | else: 118 | c_signal=signal 119 | return c_signal 120 | 121 | def TZ_integration(in_signal): 122 | lgth=in_signal.shape 123 | integral=np.zeros(lgth) 124 | c=0 125 | for indice, s in enumerate(in_signal): 126 | if indice==0: 127 | integral[indice]=c+in_signal[indice] 128 | else: 129 | integral[indice]=integral[indice-1]+in_signal[indice] 130 | return integral 131 | 132 | --------------------------------------------------------------------------------