特征提取.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. # 1.基本统计特征
  2. from flask import Flask, request, jsonify
  3. import pandas as pd
  4. from scipy.stats import skew, kurtosis
  5. import numpy as np
  6. import os
  7. import requests
  8. import math
  9. app = Flask(__name__)
  10. def ae_feature(raw, fs):
  11. mean = np.mean(raw)
  12. std_dev = np.std(raw)
  13. max_value = np.max(raw)
  14. min_value = np.min(raw)
  15. variance = np.var(raw)
  16. skewness = skew(raw)
  17. kurt = kurtosis(raw)
  18. range=np.max(raw) - np.min(raw)
  19. rms = np.sum(raw ** 2) / len(raw)
  20. ae_feature = pd.DataFrame()
  21. ae_feature['mean'] = [mean]
  22. ae_feature['std_dev'] = [std_dev]
  23. ae_feature['max_value'] = [max_value]
  24. ae_feature['min_value'] = [min_value]
  25. ae_feature['variance'] = [variance]
  26. ae_feature['skewness'] = [skewness]
  27. ae_feature['kurt'] = [kurt]
  28. ae_feature['range'] = [range]
  29. ae_feature['rms'] = [rms]
  30. return ae_feature
  31. @app.route('/statistical', methods=['POST'])
  32. def upload_file1():
  33. try:
  34. # 检查请求体中是否包含文件地址
  35. data = request.json
  36. if 'file_url' not in data:
  37. return jsonify({'code': 400, 'msg': 'No file URL provided'})
  38. file_url = request.json.get('file_url')
  39. result_file_path = request.json.get('result_file_path')
  40. # 读取数据集
  41. data = pd.read_csv('{0}'.format(file_url))
  42. # 检查是否包含时间列
  43. if 'Time' in data.columns:
  44. time_column = data['Time']
  45. df = data.drop(columns='Time')
  46. else:
  47. time_column = None
  48. df = data
  49. fs = 300 # 设置提取特征值每组的数据量
  50. all_features_df = pd.DataFrame()
  51. for i in range(int(df.shape[1])):
  52. for j in range(0, len(df), fs):
  53. end_index = min(j + fs, len(df))
  54. data_test = np.array(df.iloc[j:end_index, i])
  55. sa = ae_feature(data_test, fs)
  56. all_features_df = pd.concat([all_features_df, sa], ignore_index=True)
  57. # 将结果保存为CSV文件
  58. all_features_df.to_csv(result_file_path, index=False)
  59. # 构建返回数据,只返回文件路径
  60. return jsonify({
  61. 'code': 200,
  62. 'msg': '文件处理完成',
  63. })
  64. except Exception as e:
  65. return jsonify({
  66. 'code': 500,
  67. 'msg': str(e)
  68. })
  69. ## 2.时间域特征
  70. from scipy import fftpack
  71. def time_features(raw, fs):
  72. n = len(raw)
  73. fft_raw = abs(fftpack.fft(raw, n) * 2 / n)
  74. main_freq_index = np.where(fft_raw[0:math.floor(n / 2)] == max(fft_raw[0:math.floor(n / 2)]))
  75. f = np.linspace(0, fs, n) * fs / n
  76. peak_freq = f[main_freq_index[0][0]] # 峰值频率,单位Hz
  77. xm = np.mean(raw) # 均值
  78. xstd = np.std(raw) # 标准差
  79. kur = ((np.sum((raw - xm) ** 4)) / len(raw)) / (xstd ** 4) # 峭度
  80. cal_ave_amp = np.sum(np.abs(raw)) / n
  81. power_2 = np.power(raw, 2)
  82. sum_power = np.sum(power_2)
  83. cal_rms = np.sqrt(sum_power / n)
  84. cal_form = cal_rms / cal_ave_amp # 波峰因子,均方根/平均幅值
  85. cal_peak = np.max(np.abs(raw)) # 峰值
  86. cal_crest = cal_peak / cal_rms # 峰值因子
  87. feature_df = pd.DataFrame()
  88. feature_df['peak_freq_khz'] = [peak_freq / 1000] # 转换为kHz
  89. feature_df['均值v'] = [xm]
  90. feature_df['标准差'] = [xstd]
  91. feature_df['峭度'] = [kur]
  92. feature_df['平均幅值'] = [cal_ave_amp]
  93. feature_df['均方根'] = [cal_rms]
  94. feature_df['波峰因子'] = [cal_form]
  95. feature_df['峰值'] = [cal_peak]
  96. feature_df['峰值因子'] = [cal_crest]
  97. return feature_df
  98. @app.route('/time', methods=['POST'])
  99. def upload_file2():
  100. try:
  101. # 检查请求体中是否包含文件地址
  102. data = request.json
  103. if 'file_url' not in data:
  104. return jsonify({'code': 400, 'msg': 'No file URL provided'})
  105. file_url = request.json.get('file_url')
  106. result_file_path = request.json.get('result_file_path')
  107. # 读取数据集
  108. df = pd.read_csv('{0}'.format(file_url))
  109. fs = 300 # 每组数据量
  110. all_features_df = pd.DataFrame()
  111. for i in range(int(df.shape[1])):
  112. for j in range(0, len(df.iloc[:, i]), fs):
  113. end_index = min(j + fs, len(df.iloc[:, i]))
  114. data_test = np.array(df.iloc[j:end_index, i])
  115. sa = time_features(data_test, fs)
  116. all_features_df = pd.concat([all_features_df, sa], ignore_index=True)
  117. all_features_df.to_csv(result_file_path, index=False)
  118. # 构建返回数据,只返回文件路径
  119. return jsonify({
  120. 'code': 200,
  121. 'msg': '文件处理完成',
  122. })
  123. except Exception as e:
  124. return jsonify({
  125. 'code': 500,
  126. 'msg': str(e)
  127. })
  128. ## 3.频域特征
  129. def fe_feature(signal, fs):
  130. n = len(signal)
  131. freqs = fftfreq(n, d=1/fs) # 生成频率序列
  132. signal_fft = fft(signal) # 计算FFT
  133. signal_fft_shifted = np.fft.fftshift(signal_fft) # 将FFT结果中心化
  134. # 计算频域特征
  135. total_energy = np.sum(np.abs(signal_fft)**2)
  136. total_power = total_energy / n
  137. rms = np.sqrt(total_power)
  138. freq_centroid = np.sum(np.abs(freqs) * np.abs(signal_fft_shifted)**2) / total_energy
  139. freq_bandwidth = np.sum(np.abs(freqs[1:]**2 * signal_fft_shifted[1:]**2) - np.abs(freqs[:-1]**2 * signal_fft_shifted[:-1]**2)) / (2 * np.sum(np.abs(signal_fft_shifted)**2))
  140. peak_freq = (np.argmax(np.abs(signal_fft_shifted)) + 1) * fs / n # 峰值频率
  141. freq_skewness = skew(freqs[1:n//2] * (np.abs(signal_fft[1:n//2]) / np.max(np.abs(signal_fft[1:n//2]))))
  142. freq_kurtosis = kurtosis(freqs[1:n//2] * (np.abs(signal_fft[1:n//2]) / np.max(np.abs(signal_fft[1:n//2]))))
  143. feature_df = pd.DataFrame({
  144. '总能量': [total_energy],
  145. '总功率': [total_power],
  146. '均方根': [rms],
  147. '频率中心': [freq_centroid],
  148. '频率带宽': [freq_bandwidth],
  149. '峰值频率': [peak_freq],
  150. '频率偏度': [freq_skewness],
  151. '频率峰度': [freq_kurtosis]
  152. })
  153. return feature_df
  154. @app.route('/frequency', methods=['POST'])
  155. def upload_file3():
  156. try:
  157. # 检查请求体中是否包含文件地址
  158. data = request.json
  159. if 'file_url' not in data:
  160. return jsonify({'code': 400, 'msg': 'No file URL provided'})
  161. file_url = request.json.get('file_url')
  162. result_file_path = request.json.get('result_file_path')
  163. # 读取数据集
  164. df = pd.read_csv('{0}'.format(file_url))
  165. fs = 300 # 采样频率,根据实际情况调整
  166. all_features_df = pd.DataFrame()
  167. for i in range(int(df.shape[1])):
  168. for j in range(0, len(df.iloc[:, i]), fs):
  169. end_index = min(j + fs, len(df.iloc[:, i]))
  170. data_test = df.iloc[j:end_index, i].to_numpy()
  171. fa = fe_feature(data_test, fs)
  172. all_features_df = pd.concat([all_features_df, fa], ignore_index=True)
  173. all_features_df.to_csv(result_file_path, index=False, header=True)
  174. # 构建返回数据,只返回文件路径
  175. return jsonify({
  176. 'code': 200,
  177. 'msg': '文件处理完成',
  178. })
  179. except Exception as e:
  180. return jsonify({
  181. 'code': 500,
  182. 'msg': str(e)
  183. })
  184. # #4.时频域特征
  185. from scipy.stats import skew, kurtosis
  186. from scipy.fft import fft, fftfreq
  187. def tf_features(raw, fs):
  188. # 计算快速傅里叶变换
  189. fft_values = fft(raw)
  190. fft_magnitude = np.abs(fft_values)
  191. # 计算频率向量
  192. n = len(raw)
  193. freq = fftfreq(n, 1 / fs)
  194. # 时域特征
  195. mean = np.mean(raw)
  196. std_dev = np.std(raw)
  197. max_value = np.max(raw)
  198. min_value = np.min(raw)
  199. variance = np.var(raw)
  200. skewness = skew(raw)
  201. kurt = kurtosis(raw)
  202. # 频域特征
  203. power_spectrum = np.square(fft_magnitude) / n
  204. mean_freq = np.mean(freq[power_spectrum > 0])
  205. std_freq = np.std(freq[power_spectrum > 0])
  206. freq_skewness = skew(freq[power_spectrum > 0])
  207. freq_kurt = kurtosis(freq[power_spectrum > 0])
  208. peak_freq_index = np.argmax(power_spectrum)
  209. peak_freq = freq[peak_freq_index]
  210. bandwidth = np.max(freq[power_spectrum > 0]) - np.min(freq[power_spectrum > 0])
  211. energy = np.sum(power_spectrum)
  212. feature_df = pd.DataFrame({
  213. '均值': [mean],
  214. '标准差': [std_dev],
  215. '最大值': [max_value],
  216. '最小值': [min_value],
  217. '方差': [variance],
  218. '偏度': [skewness],
  219. '峰度': [kurt],
  220. '频率均值': [mean_freq],
  221. '频率标准差': [std_freq],
  222. '频率偏度': [freq_skewness],
  223. '频率峰度': [freq_kurt],
  224. '峰值频率': [peak_freq],
  225. '带宽': [bandwidth],
  226. '能量': [energy]
  227. })
  228. return feature_df
  229. @app.route('/time-frequency', methods=['POST'])
  230. def upload_file4():
  231. try:
  232. # 检查请求体中是否包含文件地址
  233. data = request.json
  234. if 'file_url' not in data:
  235. return jsonify({'code': 400, 'msg': 'No file URL provided'})
  236. file_url = request.json.get('file_url')
  237. result_file_path = request.json.get('result_file_path')
  238. # 读取数据集
  239. df = pd.read_csv('{0}'.format(file_url))
  240. fs = 300 # 采样频率
  241. all_features_df = pd.DataFrame()
  242. for i in range(int(df.shape[1])):
  243. for j in range(0, len(df.iloc[:, i]), fs):
  244. end_index = min(j + fs, len(df.iloc[:, i]))
  245. data_test = df.iloc[j:end_index, i].to_numpy()
  246. fa = tf_features(data_test, fs)
  247. all_features_df = pd.concat([all_features_df, fa], ignore_index=True)
  248. all_features_df.to_csv(result_file_path, index=False, header=True)
  249. # 构建返回数据,只返回文件路径
  250. return jsonify({
  251. 'code': 200,
  252. 'msg': '文件处理完成',
  253. })
  254. except Exception as e:
  255. return jsonify({
  256. 'code': 500,
  257. 'msg': str(e)
  258. })
  259. ##5.形态学特征提取
  260. from flask import Flask, request, jsonify
  261. import pandas as pd
  262. from scipy.signal import find_peaks
  263. import numpy as np
  264. def morphological_features(raw):
  265. nonzero_elements = np.count_nonzero(raw)
  266. mean_slope = np.mean(np.diff(raw) / np.diff(np.arange(len(raw))))
  267. peaks, _ = find_peaks(raw)
  268. num_peaks = len(peaks)
  269. troughs, _ = find_peaks(-raw) # 寻找谷值
  270. num_troughs = len(troughs)
  271. # 假设峰值和谷值的宽度为相邻峰值或谷值之间的距离
  272. peak_widths = np.diff(np.sort(peaks)[1:] - np.sort(peaks)[:-1]) if num_peaks > 1 else np.array([])
  273. trough_widths = np.diff(np.sort(troughs)[1:] - np.sort(troughs)[:-1]) if num_troughs > 1 else np.array([])
  274. # 计算曲率和加速度变化需要一阶和二阶导数
  275. first_derivative = np.diff(raw) / np.diff(np.arange(len(raw)))
  276. second_derivative = np.diff(first_derivative) / np.diff(np.arange(len(raw) - 1))
  277. curvature = np.sum(second_derivative ** 2) # 曲率的简单估计
  278. acceleration_change = np.sum(np.abs(np.diff(first_derivative))) # 加速度变化的简单估计
  279. feature_df = pd.DataFrame({
  280. '非零元素数': [nonzero_elements],
  281. '平均斜率': [mean_slope],
  282. '峰值数量': [num_peaks],
  283. '谷值数量': [num_troughs],
  284. '平均峰宽': [np.mean(peak_widths)] if peak_widths.size else [0],
  285. '平均谷宽': [np.mean(trough_widths)] if trough_widths.size else [0],
  286. '曲率': [curvature],
  287. '加速度变化': [acceleration_change]
  288. })
  289. return feature_df
  290. @app.route('/morphology', methods=['POST'])
  291. def upload_file5():
  292. try:
  293. # 检查请求体中是否包含文件地址
  294. data = request.json
  295. if 'file_url' not in data:
  296. return jsonify({'code': 400, 'msg': 'No file URL provided'})
  297. file_url = request.json.get('file_url')
  298. result_file_path = request.json.get('result_file_path')
  299. # 读取数据集
  300. df = pd.read_csv('{0}'.format(file_url))
  301. all_features_df = pd.DataFrame()
  302. for i in range(int(df.shape[1])):
  303. # 假设数据是等间隔采样的,fs 不再作为函数参数
  304. data_test = df.iloc[:, i].to_numpy()
  305. fa = morphological_features(data_test)
  306. all_features_df = pd.concat([all_features_df, fa], ignore_index=True)
  307. all_features_df.to_csv(result_file_path, index=False, header=True)
  308. # 构建返回数据,只返回文件路径
  309. return jsonify({
  310. 'code': 200,
  311. 'msg': '文件处理完成',
  312. })
  313. except Exception as e:
  314. return jsonify({
  315. 'code': 500,
  316. 'msg': str(e)
  317. })
  318. if __name__ == '__main__':
  319. app.run(debug=True, port=10002, host='0.0.0.0')