예제 #1
0
def detect_cycle(data: List[List[float]]) -> List[np.ndarray]:
    """
    周期检测
    :param data: 一个list,里面n个[x,y,z]
    :return: 一个list,里面m个list表示m个周期,每一个周期内包含若干个[x,y,z]
    """
    def distance(list1, list2):
        assert len(list1) == len(list2), "比较欧式距离时两个向量长度应该相等"
        s = 0
        for i in range(len(list1)):
            s = s + math.pow(list1[i] - list2[i], 2)
        return round(math.sqrt(s), 2)

    reference_length = 50  # 数据点模板长度,在50HZ的数据中,长度为50表示使用1S的模板且模板的位置选在了中间
    dis = []
    count = 0  # 这是用来划分走路周期的,在跟模板比较之后,根据波形的波谷进行划分,实际上是两个波谷才是一个完整的走路周期
    result = []
    temp = []
    x2y2z2 = [i[0] * i[0] + i[1] * i[1] + i[2] * i[2] for i in data]
    for i in range(0, len(x2y2z2) - reference_length):
        dis.append(
            distance(
                x2y2z2[i:i + reference_length],
                x2y2z2[len(x2y2z2) // 2:len(x2y2z2) // 2 + reference_length]))
    for i in range(1, len(dis) - 1):
        temp.append(data[i])
        if dis[i] < dis[i - 1] and dis[i] < dis[i + 1]:
            count = (count + 1) % 2
            if count == 0:
                result.append(np.array(temp))
                temp = []
    return result
예제 #2
0
def load_data0_data(file_name: str) -> np.ndarray:
    """
    读data0的数据
    :param file_name:
    :return:
    """
    with open(file_name, "r", encoding="utf-8") as file:
        lines = file.readlines()
        lines = [[float(v) for v in line.split(" ")] for line in lines]
        return np.array(lines)
예제 #3
0
 def get_gait_cycle(self, data: list) -> Union[np.ndarray, None]:
     """
     获取步态周期
     :return: 步态周期
     """
     if len(data) == 0:
         return None
     validate_raw_data_with_timestamp(np.array(data))
     first_cycle = self._find_first_gait_cycle(np.array(data))
     if first_cycle is None:
         # TODO count_threshold_to_clear_template 必须保证比sensor中存的最大的点数要小,不然一直无法清除模板,这里暂时都是400,没有限制
         # print(len(data))
         if len(data) >= self.count_threshold_to_clear_template:
             self.template = None
         return None
     # first_cycle = self.transform(first_cycle)
     # if len(first_cycle) > 4:  # 点的数量太少无法插值
     #     first_cycle = self.interpolate(first_cycle)
     #     return [], None
     # interpolated_cycle = self.interpolate(transformed_cycle)
     interpolated_cycle_without_transform = self.interpolate(first_cycle)
     self.cycle_count += 1
     if self.DEBUG:
         plt.plot(interpolated_cycle_without_transform[:, 1],
                  "r",
                  label="x")
         plt.plot(interpolated_cycle_without_transform[:, 2],
                  "g",
                  label="y")
         plt.plot(interpolated_cycle_without_transform[:, 3],
                  "b",
                  label="z")
         plt.title("interpolated_cycle")
         plt.legend()
         plt.show()
     if self.DEBUG:
         logger.debug("{0}:CYCYLE INDEX:{1}".format(self.data_type,
                                                    self.cycle_count))
     return np.concatenate(
         (np.array([self._mag(interpolated_cycle_without_transform[:, 1:])
                    ]).T, interpolated_cycle_without_transform[:, 1:]),
         axis=1)
예제 #4
0
def chazhi(data: list, point_number_per_cycle=100) -> np.ndarray:
    """
    对数据进行插值
    :param point_number_per_cycle: 插值之后每个周期内的数据点个数
    :param data: 一个list,里面是n个list,每个list里面是若干个[x,y,z]
    :return: 一个list,里面是n个list,每个list里面是:POINT_NUMBER_PER_CYCLE个插值完的[x,y,z]
    """
    for i, data_i in enumerate(data):
        data_i = np.array(data_i)
        x_old, y_old, z_old = data_i[:, 0], data_i[:, 1], data_i[:, 2]
        x = np.linspace(0, len(data_i), len(data_i))
        x_index = np.linspace(0, len(data_i), point_number_per_cycle)
        new_x = interpolate.interp1d(x, x_old, kind="quadratic")(x_index)
        new_y = interpolate.interp1d(x, y_old, kind="quadratic")(x_index)
        new_z = interpolate.interp1d(x, z_old, kind="quadratic")(x_index)
        temp = []
        for j in range(len(new_x)):
            temp.append((new_x[j], new_y[j], new_z[j]))
        data[i] = np.array(temp)
    return np.array(data)
예제 #5
0
 def _mag(self, data: np.ndarray) -> np.ndarray:
     """
     计算合加速度
     :param data:
     :return:
     """
     validate_raw_data_without_timestamp(data)
     result = np.array(
         [math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]) for d in data])
     # return self.lowpass(result)
     return result
예제 #6
0
 def update(self):
     """
     更新曲线数据
     :return:
     """
     data = np.array(self.get_raw_data())
     if data.any():
         validate_raw_data_with_timestamp(data)
         t = list(range(len(data)))
         self.line_x.set_data(t, data[:, 1])
         self.line_y.set_data(t, data[:, 2])
         self.line_z.set_data(t, data[:, 3])
예제 #7
0
 def visualize(self):
     """
     网络可视化
     :return:
     """
     """
     _________________________________________________________________
     Layer (type)                 Output Shape              Param #   
     =================================================================
     input_1 (InputLayer)         (None, 8, 200, 1)         0         
     _________________________________________________________________
     conv2d_1 (Conv2D)            (None, 8, 191, 20)        220       
     _________________________________________________________________
     conv2d_2 (Conv2D)            (None, 5, 182, 40)        32040     
     _________________________________________________________________
     max_pooling2d_1 (MaxPooling2 (None, 2, 91, 40)         0         
     _________________________________________________________________
     flatten_1 (Flatten)          (None, 7280)              0         
     _________________________________________________________________
     dense_1 (Dense)              (None, 40)                291240    
     _________________________________________________________________
     dense_2 (Dense)              (None, 10)                410       
     =================================================================
     """
     data, label = self._load_data()
     data = np.reshape(data, data.shape + (1, ))
     activation_model = Model(
         inputs=[self.model.input],
         outputs=[layer.output for layer in self.model.layers[1:3]])
     activations = activation_model.predict(np.array([data[3]]))
     """
     >>> len(activations)
     2    # 两层
     >>> activations[0].shape
     (1, 8, 191, 20) 
     """
     filter_count = 20
     display_layer = 1  # 展示的第几层
     display_mat = np.zeros(
         (filter_count * activations[display_layer][0].shape[0],
          activations[display_layer][0].shape[1]))
     for i in range(filter_count):
         channel_image = activations[display_layer][0, :, :, i]
         channel_image -= channel_image.mean()
         channel_image /= channel_image.std()
         channel_image *= 64
         channel_image += 128
         channel_image = np.clip(channel_image, 0, 255).astype("uint8")
         display_mat[i * activations[display_layer][0].shape[0]:(i + 1) *
                     activations[display_layer][0].shape[0], :
                     activations[display_layer][0].shape[1]] = channel_image
     plt.matshow(display_mat)
     plt.show()
예제 #8
0
def load_data0_cycle() -> Tuple[np.ndarray, np.ndarray]:
    """
    载入用data0生成的步态周期数据
    :return:
    """
    data_file_full_name = os.path.join(CYCLE_FILE_DIR, "data")
    if not os.path.exists(data_file_full_name):
        logger.debug("data0 cycle数据不存在,开始生成")
        data, label = [], []
        from sensor.sensor import SensorManager
        from sensor.algorithm.data_pre_process import AccDataPreProcess, GyroDataPreProcess
        for i in range(10):
            sensor_manager = SensorManager(i)
            acc_data_pre_process = AccDataPreProcess(sensor_manager)
            gyro_data_pre_process = GyroDataPreProcess(sensor_manager)
            acc_cycles = []
            gyro_cycles = []
            while True:
                get_data_result = sensor_manager.update_display_raw_data()
                if not get_data_result:
                    break
                sensor_manager.acc_to_display, acc_cycle = acc_data_pre_process.get_gait_cycle(
                    sensor_manager.acc_to_display)
                sensor_manager.gyro_to_display, gyro_cycle = gyro_data_pre_process.get_gait_cycle(
                    sensor_manager.gyro_to_display)
                if acc_cycle is not None:
                    acc_cycles.append(acc_cycle)
                if gyro_cycle is not None:
                    gyro_cycles.append(gyro_cycle)
            for acc_cycle, gyro_cycle in zip(acc_cycles, gyro_cycles):
                data.append(np.concatenate((acc_cycle, gyro_cycle), axis=1))
                label.append(i)
            logger.debug("生成CNN数据:{0}".format(i))
        with open(data_file_full_name, "wb") as file:
            file.write(pickle.dumps((np.array(data), np.array(label))))
    with open(data_file_full_name, "rb") as file:
        data, label = pickle.loads(file.read())
    assert isinstance(data, np.ndarray) and len(
        data.shape) == 3 and data.shape[1] == 200 and data.shape[2] == 8
    return data.transpose((0, 2, 1)), label  # 数据是200 * 8的,训练需要8 * 200
예제 #9
0
 def _get_feature(self, data: np.ndarray) -> np.ndarray:
     """
     生成用于分类的特征
     :param data:
     :return:
     """
     assert len(data.shape) == 2 and data.shape[1] == 4, "one class分类器生成特征数据格式异常"
     result = np.array([])
     # 平均值
     result = np.append(result, np.average(data, axis=0))
     # 标准差
     result = np.append(result, np.std(data, axis=0))
     return result
예제 #10
0
def split_data(data: np.ndarray,
               label: np.ndarray,
               ratio: tuple = (0.8, 0, 0.2),
               **kwargs):
    """
    把数据和标签分为训练集、验证集和测试集
    :param data:
    :param label:
    :param ratio:
    :param kwargs: :normalization 表示归一化, :to_categorical表示将label进行one-hot编码
    :return:
    """
    data = pop_timestamp(data)
    data = np.array(data)
    label = np.array(label)
    if "normalization" in kwargs:
        mean = data.mean()
        data = data - mean
        std = data.std()
        data = data / std
    index = np.arange(len(data))
    np.random.shuffle(index)
    data = data[index]
    label = label[index]
    if "to_categorical" in kwargs:
        label = to_categorical(label)
    train_data_number = int(len(data) * ratio[0])
    validate_data_number = int(len(data) * ratio[1])
    train_data, train_label = data[:
                                   train_data_number], label[:
                                                             train_data_number]
    validate_data, validate_label = data[
        train_data_number:train_data_number +
        validate_data_number], label[train_data_number:train_data_number +
                                     validate_data_number]
    test_data, test_label = data[train_data_number +
                                 validate_data_number:], label[
                                     train_data_number + validate_data_number:]
    return train_data, train_label, validate_data, validate_label, test_data, test_label
예제 #11
0
 def test_model(self):
     """
     随机挑几个数来测试模型
     :return:
     """
     data, label = load_data0_cycle()
     data = np.reshape(data, data.shape + (1, ))
     for i in range(10):
         index = random.choice(range(len(data)))
         predict_index = np.argmax(
             self.model.predict(np.array([data[index]])))
         print("index:{0},预测值:{1},实际值:{2},预测成功:{3}".format(
             index, predict_index, label[index],
             bool(predict_index == label[index])))
예제 #12
0
 def _load_data(self) -> Tuple[np.ndarray, np.ndarray]:
     acc_data_full_path = os.path.join(self.HHAR_DATA_PATH, "Watch_accelerometer")
     if os.path.isfile(acc_data_full_path):
         logger.info("{0}训练数据已经存在".format(self.network_name))
     else:
         logger.info("{0}训练数据不存在".format(self.network_name))
         data, label = [], []
         with open(os.path.join(self.HHAR_DATA_PATH, "Watch_accelerometer.csv"), "r") as file:
             tmp_data = []
             reader = csv.DictReader(file)
             last_label = None
             last_time = None
             for line in reader:
                 cur_label = self.LABEL_MAP.get(line.get("gt"))
                 cur_time = int(line.get("Arrival_Time"))
                 if not last_time:
                     last_time = cur_time
                 elif cur_time - last_time < 20:
                     continue
                 else:
                     last_time = cur_time
                 if cur_label == last_label:
                     tmp_data.append([float(line.get("x")), float(line.get("y")), float(line.get("z"))])
                 else:
                     if not cur_label:
                         continue
                     cycles = detect_cycle(tmp_data)
                     cycles = chazhi(cycles)
                     data.extend(cycles)
                     label.extend([last_label for _ in range(len(cycles))])
                     last_label = cur_label
                     tmp_data.clear()
         with open(acc_data_full_path, "wb") as file:
             file.write(pickle.dumps((data, label)))
     with open(acc_data_full_path, "rb") as file:
         data = pickle.loads(file.read())
         return np.array(data[0]), np.array(data[1])
예제 #13
0
 def update_cycle_detect_result(self, is_walking):
     """
     更新步态检测结果,用于在GUI上显示历史记录
     :param is_walking:
     :return:
     """
     if self.acc_data_pre_process.last_cycle is not None:
         print(self.acc_one_class_svm.predict(np.array([self.acc_data_pre_process.last_cycle])))
     if is_walking:
         if self.acc_data_pre_process.last_cycle is not None or self.gyro_data_pre_process.last_cycle is not None:
             self.cycle_detect_history[CycleDetectResult.CYCLE_DETECTED] += 1
         else:
             self.cycle_detect_history[CycleDetectResult.WALK_BUT_NO_CYCLE] += 1
     else:
         self.cycle_detect_history[CycleDetectResult.NOT_WALKING] += 1
예제 #14
0
 def interpolate(self, data: np.ndarray) -> np.ndarray:
     """
     对数据进行插值
     :param data: 一个list,里面是n个list,每个list里面是若干个[x,y,z]
     :return: 一个list,里面是n个list,每个list里面是:POINT_NUMBER_PER_CYCLE个插值完的[x,y,z]
     """
     validate_raw_data_with_timestamp(
         data)  # 这里也是有四列,不过第一列不是时间而是合成加速度,校验函数通用
     mag_old, x_old, y_old, z_old = data[:, 0], data[:, 1], data[:,
                                                                 2], data[:,
                                                                          3]
     x = np.linspace(0, len(data), len(data))
     x_index = np.linspace(0, len(data), self.point_count_per_cycle)
     new_mag = interpolate.interp1d(x, mag_old, kind="quadratic")(x_index)
     new_x = interpolate.interp1d(x, x_old, kind="quadratic")(x_index)
     new_y = interpolate.interp1d(x, y_old, kind="quadratic")(x_index)
     new_z = interpolate.interp1d(x, z_old, kind="quadratic")(x_index)
     return np.array([new_mag, new_x, new_y, new_z]).T
예제 #15
0
 def _is_walking(self) -> bool:
     """
     判断当前是否在行走,直接阈值判断
     :return:
     """
     mag_interval = (20, 900)
     test_data = np.array(self._sensor_manager.acc_to_display[-100:])
     if not len(test_data):
         return False
     mag = [d[1] * d[1] + d[2] * d[2] + d[3] * d[3] for d in test_data]
     is_mag_ok = min(mag) >= mag_interval[0] and max(mag) <= mag_interval[1]
     ok_threshold = 5
     is_x_ok = max(test_data[:, 1]) - min(test_data[:, 1]) > ok_threshold
     is_y_ok = max(test_data[:, 2]) - min(test_data[:, 2]) > ok_threshold
     is_z_ok = max(test_data[:, 3]) - min(test_data[:, 3]) > ok_threshold
     is_walking = is_mag_ok and (is_x_ok or is_y_ok or is_z_ok)
     if not is_walking:  # 没在走路的话去清空数据
         self._sensor_manager.clear_data_to_detect_cycle()
     # self._sensor_manager.send_msg(bytes("行走:{0}".format(is_walking),encoding="utf-8"))
     return is_walking
예제 #16
0
 def _find_new_template(self, data) -> Union[np.ndarray, None]:
     """
     初始化的时候或者找不到步态周期的时候需要重新寻找模板
     step1:寻找第一个局部最小点
     step2:在局部最小点周围1S内寻找最小点
     step3:最小点周围1S作为模板
     :param data:
     :return:
     """
     validate_raw_data_with_timestamp(data)
     mags = np.array(
         [math.sqrt(d[1] * d[1] + d[2] * d[2] + d[3] * d[3]) for d in data])
     for index in range(len(mags)):
         # step1
         if 0 < index < len(mags) - 1 and mags[index] < min(
                 mags[index - 1], mags[index + 1]):
             start, end = index, index
             while start >= 0 and end < len(mags) and data[end][0] - data[
                     start][0] < self.template_duration:
                 start -= 1
                 end += 1
             # step2
             if start < 0 or end >= len(mags):
                 continue
             window_around_local_minimum = mags[start:end]
             # step3
             minimum_point_index = start + np.argmin(
                 window_around_local_minimum)
             start, end = minimum_point_index, minimum_point_index
             while start >= 0 and end < len(data) and data[end][0] - data[
                     start][0] < self.template_duration:
                 start -= 1
                 end += 1
             if start < 0 or end >= len(data):
                 continue
             # TODO 实时数据acc有问题是因为这里模板找的太长了 100
             # print(end - start)
             # print("start end", data[start:end+1])
             # print(end - start + 1)
             return self._mag(data[start:end][:, 1:])
     return None
예제 #17
0
 def get_current_activity(self) -> str:
     """
     获取当前的运动状态
     :return:
     """
     # 预测动作
     if len(self._sensor_manager.acc_to_display) >= 100:
         predict_result = self.activity_recognition_network.predict(
             [np.array(self._sensor_manager.acc_to_display)[-100:, 1:]])
         predict_number = int(np.argmax(predict_result[0]))
         # self._sensor_manager.conn.send(str(predict_number).encode("utf-8"))
         m = {
             0: "骑车",
             1: "静止",
             2: "步行",
             3: "上楼",
             4: "下楼",
         }
         if self.is_walking:
             return "步行"
         return m.get(predict_number)
     else:
         return ""
예제 #18
0
 def transform(self, matrix_a: np.ndarray) -> np.ndarray:
     """
     将步态周期进行坐标转换
     :param matrix_a: 周期
     :return:
     """
     validate_raw_data_with_timestamp(matrix_a)
     matrix_a = matrix_a[:, 1:]
     vector_p_k = np.average(matrix_a, axis=0).T
     vector_n1 = vector_p_k / np.linalg.norm(vector_p_k)  # 一撇撇
     vector_a_n1 = np.dot(matrix_a, vector_n1)
     matrix_a_f = matrix_a - np.dot(vector_a_n1[:, np.newaxis],
                                    vector_n1[np.newaxis, :])
     u = np.average(matrix_a_f, axis=0)
     matrix_a_norm_f = matrix_a_f - u
     sigma = np.dot(matrix_a_norm_f.T,
                    matrix_a_norm_f) / (matrix_a.shape[0] - 1)
     eigenvalue, eigenvector = np.linalg.eig(sigma)
     vector_n2 = eigenvector[np.argmax(eigenvalue)]  # 两撇撇
     vector_n3 = np.cross(vector_n1, vector_n2)
     vector_a_n2 = np.dot(matrix_a, vector_n2)
     vector_a_n3 = np.dot(matrix_a, vector_n3)
     return np.array(
         [self._mag(matrix_a), vector_a_n1, vector_a_n2, vector_a_n3]).T
예제 #19
0
 def predict(self, data: list):
     data = np.array(data)
     return self.model.predict(data)
예제 #20
0
 def _find_first_gait_cycle(self,
                            data: np.ndarray) -> Union[np.ndarray, None]:
     """
     检测寻找第一个步态周期
     :param data: 原始数据
     :return: 步态周期
     """
     validate_raw_data_with_timestamp(data)
     mags = self._mag(data[:, 1:])
     if self.template is None:
         self.template = self._find_new_template(data)
         # print("template", self.template)
         # if self.template is not None:
         #     print(len(self.template))
     if self.template is None:
         return None
     cycle_index_points = []
     corr_distance = []
     for i in range(len(mags) - len(self.template) + 1):
         corr_distance.append(
             self._corr_distance(self.template,
                                 mags[i:i + len(self.template)]))
     corr_distance = self._lowpass(np.array(corr_distance))
     for i in range(len(corr_distance)):
         if i >= 2 and corr_distance[i - 1] < min(corr_distance[i - 2], corr_distance[i]) and \
                 corr_distance[i - 1] < self.gait_cycle_threshold:
             cycle_index_points.append(i - 1)
             if len(cycle_index_points) == 2:
                 # 如果找到的周期时间不够的话,就凑上下一个周期
                 self.cycle_duration = int(
                     data[cycle_index_points[1]][0]) - int(
                         data[cycle_index_points[0]][0])
                 if self.cycle_duration < self.expect_gait_cycle_duration[0]:
                     del cycle_index_points[-1]
                     continue
                 elif self.cycle_duration > self.expect_gait_cycle_duration[
                         1]:
                     cycle_index_points[0] = cycle_index_points[1]
                     del cycle_index_points[-1]
                     continue
             if len(cycle_index_points) == 3:
                 self.cycle_duration = int(
                     data[cycle_index_points[2]][0]) - int(
                         data[cycle_index_points[1]][0])
                 if self.cycle_duration < self.expect_gait_cycle_duration[0]:
                     del cycle_index_points[-1]
                     continue
                 elif self.cycle_duration > self.expect_gait_cycle_duration[
                         1]:
                     cycle_index_points[0] = cycle_index_points[2]
                     del cycle_index_points[-1]
                     del cycle_index_points[-1]
                     continue
             if len(cycle_index_points) == 4:
                 self.cycle_duration = int(
                     data[cycle_index_points[3]][0]) - int(
                         data[cycle_index_points[2]][0])
                 if self.cycle_duration < self.expect_gait_cycle_duration[0]:
                     del cycle_index_points[-1]
                     continue
                 elif self.cycle_duration > self.expect_gait_cycle_duration[
                         1]:
                     cycle_index_points[0] = cycle_index_points[3]
                     del cycle_index_points[-1]
                     del cycle_index_points[-1]
                     del cycle_index_points[-1]
                     continue
                 if self.last_cycle_to_locate is None:
                     cycle = data[
                         cycle_index_points[0]:cycle_index_points[2] + 1]
                     self.last_cycle_to_locate = cycle
                     if self.DEBUG:
                         use_first_cycle = True
                 else:
                     cycle1 = data[
                         cycle_index_points[0]:cycle_index_points[2] + 1]
                     cycle2 = data[
                         cycle_index_points[1]:cycle_index_points[3] + 1]
                     if self.fast_dtw(
                             self.last_cycle_to_locate[:, 3],
                             cycle1[:, 3]) < self.fast_dtw(
                                 self.last_cycle_to_locate[:, 3],
                                 cycle2[:, 3]):  # 使用4格 + z轴fastdtw来寻找周期
                         cycle = cycle1
                         if self.DEBUG:
                             use_first_cycle = True
                     else:
                         cycle = cycle2
                         if self.DEBUG:
                             use_first_cycle = False
                     self.last_cycle_to_locate = self._update_last_cycle(
                         cycle)
                 if self.DEBUG:
                     plt.cla()
                     plt.plot(data[:, 1], "r", label="x")
                     plt.plot(data[:, 2], "g", label="y")
                     plt.plot(data[:, 3], "b", label="z")
                     plt.plot(self._mag(data[:, 1:]), "black", label="mag")
                     plt.plot(corr_distance, "y", label="dis")
                     plt.axvline(cycle_index_points[0],
                                 color="r" if use_first_cycle else "b")
                     plt.axvline(cycle_index_points[1],
                                 color="r" if not use_first_cycle else "b")
                     plt.axvline(cycle_index_points[2],
                                 color="r" if use_first_cycle else "b")
                     plt.axvline(cycle_index_points[3],
                                 color="r" if not use_first_cycle else "b")
                     plt.legend()
                     plt.title("search cycle")
                     plt.show()
                 self.template = self._update_template(cycle)
                 return cycle
     return None