赞
踩
由于算法要运行在手表上,算力和内存空间有限,需要进行内存压缩和c代码实现。
Status_detection.c
- #include <stdio.h>
- #include <stdbool.h>
- #include <math.h>
- #include <stdlib.h>
-
-
- #define buf_p 7
- #define EPS 0.000001
- float g_Tx[250], g_Tx1[250];
- float g_Sp[20], g_Tvec[20], g_Zi[20];
- int g_Is[10], g_Js[10];
-
- float b_ppg[3] = { 0.0133592,0.0267184,0.0133592 };
- float a_ppg[3] = { 1, -1.64745998, 0.70089678 };//b_u和a_u为滤波器参数
-
- void Filter(const float* x, float* y, int xlen, float* a, float* b, int nfilt, float* g_Zi)//nfilt为系数数组长度,g_Zi为延时系数
- {
- float tmp;
- int i, j;
- //判断a[0]是否为1,若不是,归一化下
- if ((*a - 1.0 > EPS) || (*a - 1.0 < -EPS))
- {
- tmp = *a;
- for (i = 0; i < nfilt; i++)
- {
- b[i] /= tmp;
- a[i] /= tmp;
- }
- }
- memset(y, 0, xlen * sizeof(float));//将y清零,以双浮点为单位
- a[0] = 0.0;
- for (i = 0; i < xlen; i++)
- {
- for (j = 0; i >= j && j < nfilt; j++)
- {
- y[i] += (b[j] * x[i - j] - a[j] * y[i - j]);
- }
- //滤波器阶数大于2就加上延时系数
- if (g_Zi&&i < nfilt - 1) y[i] += g_Zi[i];
- }
- a[0] = 1.0;//还原滤波系数
- }
- //矩阵乘法 ,第一个矩阵列数必须要和第二个矩阵的行数相同,输出结果存放在c中
- void Trmul(float *a, float *b, float *c, int m, int n, int k)
- {
- int i, j, l, u;
- for (i = 0; i <= m - 1; i++)
- for (j = 0; j <= k - 1; j++)
- {
- u = i * k + j; c[u] = 0.0;
- for (l = 0; l <= n - 1; l++)
- c[u] = c[u] + a[i*n + l] * b[l*k + j];
- }
- return;
- }
- //求逆矩阵,当返回值为0时成功,a变为逆矩阵
- int Rinv(float *a, int n)
- {
- int i, j, k, l, u, v;
- float d, p;
- for (k = 0; k <= n - 1; k++)
- {
- d = 0.0;
- for (i = k; i <= n - 1; i++)
- for (j = k; j <= n - 1; j++)
- {
- l = i * n + j; p = fabs(a[l]);
- if (p > d) { d = p; g_Is[k] = i; g_Js[k] = j; }
- }
- if (g_Is[k] != k)
- for (j = 0; j <= n - 1; j++)
- {
- u = k * n + j; v = g_Is[k] * n + j;
- p = a[u]; a[u] = a[v]; a[v] = p;
- }
- if (g_Js[k] != k)
- for (i = 0; i <= n - 1; i++)
- {
- u = i * n + k; v = i * n + g_Js[k];
- p = a[u]; a[u] = a[v]; a[v] = p;
- }
- l = k * n + k;
- a[l] = 1.0 / a[l];
- for (j = 0; j <= n - 1; j++)
- if (j != k)
- {
- u = k * n + j; a[u] = a[u] * a[l];
- }
- for (i = 0; i <= n - 1; i++)
- if (i != k)
- for (j = 0; j <= n - 1; j++)
- if (j != k)
- {
- u = i * n + j;
- a[u] = a[u] - a[i*n + k] * a[k*n + j];
- }
- for (i = 0; i <= n - 1; i++)
- if (i != k)
- {
- u = i * n + k; a[u] = -a[u] * a[l];
- }
- }
- for (k = n - 1; k >= 0; k--)
- {
- if (g_Js[k] != k)
- for (j = 0; j <= n - 1; j++)
- {
- u = k * n + j; v = g_Js[k] * n + j;
- p = a[u]; a[u] = a[v]; a[v] = p;
- }
- if (g_Is[k] != k)
- for (i = 0; i <= n - 1; i++)
- {
- u = i * n + k; v = i * n + g_Is[k];
- p = a[u]; a[u] = a[v]; a[v] = p;
- }
- }
- return(0);
- }
- int FiltFilt(float* x, float* y, int len)
- {
- // int nfact = 4;
- int nfact = 2;
-
- int tlen; //length of g_Tx
- int i;
- float *p, *t, *end;
- float tmp, tmp1;
- //float sum = 0.0;
- //float average = 0.0;
- //for (int p = 0; p < len; p++)
- //{
- // sum += x[p];
- //}
- //average = (float)sum / len;
- printf("平均值 = %.2f", average);
- //for (int p = 0; p < len; ++p)
- //{
- // x[p] = x[p] - average;
- // //x2[p] = -1 * x2[p];
- //}
- //镜像到至少三倍长度
- tlen = 6 * nfact + len;
- tmp = x[0];
- for (p = x + 3 * nfact, t = g_Tx; p > x; --p, ++t)
- *t = 2.0*tmp - *p;
- for (end = x + len; p < end; ++p, ++t)
- *t = *p;
- tmp = x[len - 1];
- for (end = g_Tx + tlen, p -= 2; t < end; --p, ++t)
- *t = 2.0*tmp - *p;
- //g_Tx初始化
- end = g_Sp + nfact * nfact;
- p = g_Sp;
- // while (p < end) *p++ = 0.0L;
- while (p < end) *p++ = 0.0f;
- g_Sp[0] = 1.0 + a_ppg[1];
- for (i = 1; i < nfact; i++)
- {
- g_Sp[i*nfact] = a_ppg[i + 1];
- /* g_Sp[i*nfact + i] = 1.0L;
- g_Sp[(i - 1)*nfact + i] = -1.0L;*/
- g_Sp[i*nfact + i] = 1.0f;
- g_Sp[(i - 1)*nfact + i] = -1.0f;
- }
- for (i = 0; i < nfact; i++)
- {
- g_Tvec[i] = b_ppg[i + 1] - a_ppg[i + 1] * b_ppg[0];
- }
- if (Rinv(g_Sp, nfact))
- {
- for (i = 0; i < 50; i++)
- {
- g_Zi[i] = 0;
- }
- }
- else
- {
- Trmul(g_Sp, g_Tvec, g_Zi, nfact, nfact, 1);
- } //g_Zi延迟系数计算
- //1st filter
- tmp1 = g_Tx[0];
- if (g_Zi)
- for (p = g_Zi, end = g_Zi + nfact; p < end;) *(p++) *= tmp1;
- {
- //Filter(g_Tx, g_Tx1, tlen, a_ppg, b_ppg, 5, g_Zi);
- Filter(g_Tx, g_Tx1, tlen, a_ppg, b_ppg, 3, g_Zi);
- }
- //翻转g_Tx1
- for (p = g_Tx1, end = g_Tx1 + tlen - 1; p < end; p++, end--)
- {
- tmp = *p;
- *p = *end;
- *end = tmp;
- }
- //2nd filter
- tmp1 = (*g_Tx1) / tmp1;
- if (g_Zi)
- for (p = g_Zi, end = g_Zi + nfact; p < end;) *(p++) *= tmp1;
- {
- //Filter(g_Tx1, g_Tx, tlen, a_ppg, b_ppg, 5, g_Zi);
- Filter(g_Tx1, g_Tx, tlen, a_ppg, b_ppg, 3, g_Zi);
- }
- //output
- end = y + len;
- p = g_Tx + 3 * nfact + len - 1;
- while (y < end)
- {
- *y++ = *p--;
- }
- return 0;
- }
-
-
- // 需要滤波,否则会出现两个波峰/波谷的情况(在波峰/波谷处是直线,则会出现此情况)
- // 寻找波峰
- short FindPeak1(float *arr, short *peak_index)
- {
- short n = 0;
- for (short i = 1; i < 199; i++)
- {
- if (arr[i]>arr[i-1] && arr[i] > arr[i + 1] && n < 33)
- {
- peak_index[n] = i;
- n += 1;
- }
- }
- return n;
- }
-
- // 寻找波谷
- short FindPeak2(float *arr, short *peak_index)
- {
- short n = 0;
- for (short i = 1; i < 199; i++)
- {
- if (arr[i] < arr[i - 1] && arr[i] < arr[i + 1] && n < 33)
- {
- peak_index[n] = i;
- n += 1;
- }
- }
- return n;
- }
-
-
- // 跑步状态检测
- short RunStateDetection(float arr[], float data[], short peak1_index[], short peak2_index[], float allPeak1[], short allPeak1_index[], short allPeak1_nums[],
- float allPeak2[], short allPeak2_index[], short allPeak2_nums[])
- {
- short i = 0;
-
- // 1.低通滤波
- FiltFilt(arr, data, 200);
-
- // 2.寻找波峰/波谷
- for (i = 0; i < 33; i++)
- {
- peak1_index[i] = 0;
- peak2_index[i] = 0;
- }
- short peak1_nums = FindPeak1(data, peak1_index);
- short peak2_nums = FindPeak2(data, peak2_index);
-
- // 3.纠正波峰波谷
- if (allPeak1_nums[0] ==0 && allPeak2_nums[0] == 0) // 0条记录
- {
- // peak1
- for (i = 0; i < peak1_nums; i++)
- {
- allPeak1[i] = data[peak1_index[i]];
- allPeak1_index[i] = peak1_index[i];
- }
- allPeak1_nums[0] = peak1_nums;
-
- // peak2
- for (i = 0; i < peak2_nums; i++)
- {
- allPeak2[i] = data[peak2_index[i]];
- allPeak2_index[i] = peak2_index[i];
- }
- allPeak2_nums[0] = peak2_nums;
- }
- else // 有历史记录
- {
- short nums;
- if (allPeak1_nums[1] == 0 && allPeak2_nums[1] == 0)
- {
- nums = 1;
- }
- else if (allPeak1_nums[2] == 0 && allPeak2_nums[2] == 0)
- {
- nums = 2;
- }
- else
- {
- nums = 2;
-
- // 重置peak数据
- for (i = 0; i < 100; i++)
- {
- // peak1
- allPeak1[i] = (i < allPeak1_nums[1] + allPeak1_nums[2]) ? (allPeak1[allPeak1_nums[0] + i]) : 0;
- allPeak1_index[i] = (i < allPeak1_nums[1] + allPeak1_nums[2]) ? (allPeak1_index[allPeak1_nums[0] + i] - 200) : 0;
-
- // peak2
- allPeak2[i] = (i < allPeak2_nums[1] + allPeak2_nums[2]) ? (allPeak2[allPeak2_nums[0] + i]) : 0;
- allPeak2_index[i] = (i < allPeak2_nums[1] + allPeak2_nums[2]) ? (allPeak2_index[allPeak2_nums[0] + i] - 200) : 0;
- }
-
- for (i = 1; i < 3; i++)
- {
- allPeak1_nums[i - 1] = allPeak1_nums[i];
- allPeak2_nums[i - 1] = allPeak2_nums[i];
- }
- allPeak1_nums[2] = 0;
- allPeak2_nums[2] = 0;
- }
-
- // peak1
- short base_index1 = 0;
- short base_index2 = 0;
- for (i = 0; i < nums; i++)
- {
- base_index1 += allPeak1_nums[i];
- base_index2 += allPeak2_nums[i];
- }
-
- if (peak1_nums > 0 && peak2_nums > 0)
- {
- // 如果当前数据的第一个点是波峰,历史的最后一个点也是波峰,则删除当前第一个波峰
- if (peak1_index[0]<peak2_index[0] && allPeak1_index[base_index1 - 1]>allPeak2_index[base_index2 - 1])
- {
- for (i = 1; i < 33; i++)
- {
- peak1_index[i - 1] = (i < peak1_nums) ? peak1_index[i] : 0;
- }
- peak1_nums = peak1_nums - 1;
- }
-
- for (i = 0; i < peak1_nums; i++)
- {
- allPeak1[base_index1 + i] = data[peak1_index[i]];
- allPeak1_index[base_index1 + i] = peak1_index[i] + 200 * nums;
- }
- allPeak1_nums[nums] = peak1_nums;
- }
-
- // peak2
- if (peak1_nums > 0 && peak2_nums > 0)
- {
- // 如果当前数据的第一个点是波谷,历史的最后一个点也是波谷,则删除当前第一个波谷
- if (peak1_index[0]>peak2_index[0] && allPeak1_index[base_index1 - 1]<allPeak2_index[base_index2 - 1])
- {
- for (i = 1; i < 33; i++)
- {
- peak2_index[i - 1] = (i < peak2_nums) ? peak2_index[i] : 0;
- }
- peak2_nums = peak2_nums - 1;
- }
-
- for (i = 0; i < peak2_nums; i++)
- {
- allPeak2[base_index2 + i] = data[peak2_index[i]];
- allPeak2_index[base_index2 + i] = peak2_index[i] + 200 * nums;
- }
- allPeak2_nums[nums] = peak2_nums;
- }
- }
-
- // 4.删除开头和结尾的波峰点
- short peak1_total;
- short peak2_total;
- peak1_total = allPeak1_nums[0] + allPeak1_nums[1] + allPeak1_nums[2];
- if (allPeak1_index[0] < allPeak2_index[0]) // 开头
- {
- for (i = 1; i < 100; i++)
- {
- allPeak1_index[i - 1] = (i < peak1_total) ? allPeak1_index[i] : 0;
- allPeak1[i - 1] = (i < peak1_total) ? allPeak1[i] : 0;
- }
- allPeak1_nums[0] = allPeak1_nums[0] - 1;
- }
- peak1_total = allPeak1_nums[0] + allPeak1_nums[1] + allPeak1_nums[2];
- peak2_total = allPeak2_nums[0] + allPeak2_nums[1] + allPeak2_nums[2];
- if (allPeak1_index[peak1_total-1] > allPeak2_index[peak2_total -1]) // 结尾
- {
- for (i = 0; i < 100; i++)
- {
- allPeak1_index[i] = (i < peak1_total - 1) ? allPeak1_index[i] : 0;
- allPeak1[i] = (i < peak1_total - 1) ? allPeak1[i] : 0;
- }
-
- if (allPeak1_nums[1] == 0 && allPeak2_nums[1] == 0)
- {
- allPeak1_nums[0] = allPeak1_nums[0] - 1;
- }
- else if (allPeak1_nums[2] == 0 && allPeak2_nums[2] == 0)
- {
- allPeak1_nums[1] = allPeak1_nums[1] - 1;
- }
- else
- {
- allPeak1_nums[2] = allPeak1_nums[2] - 1;
- }
-
- }
-
- // 5.计算步数
- short step = 0;
- peak1_total = allPeak1_nums[0] + allPeak1_nums[1] + allPeak1_nums[2];
- peak2_total = allPeak2_nums[0] + allPeak2_nums[1] + allPeak2_nums[2];
- if (peak1_total< peak2_total)
- {
- for (i = 0; i < peak1_total; i++)
- {
- short distance1 = allPeak2_index[i + 1] - allPeak2_index[i];
- short distance2 = allPeak1[i] - allPeak2[i];
- if (distance1 > 25 && distance2 > 3000)
- {
- step += 1;
- }
- }
- }
-
- // 6.判断结果,2-跑步,0-非跑步
- short pred=0;
- pred = (step >= 5) ? 2 : 0;
-
- return pred;
- }
-
-
-
- void main()
- {
- float arr[] = { 3526, 3104, 2735, 2496, 2421, 2443, 2434, 2341, 2247, 2294, 2565, 3082, 3764, 4497, 5083, 5355, 5457, 5624, 5996, 6515, 6919, 7095, 7147, 7157, 7079, 6848, 6440, 5927, 5431, 4994, 4574, 4082, 3445, 2707, 2011, 1473, 1125, 877, 657, 471, 366, 417, 688, 1129, 1691, 2405, 3044, 3444, 3728, 3617, 3596, 6522, 11834, 13959, 12571, 10776, 9181, 7522, 6433, 5821, 5226, 4994, 4928, 4797, 4640, 4284, 3752, 3082, 2433, 2075, 1797, 1849, 2122, 2317, 2417, 2472, 2730, 3188, 3670, 4428, 5278, 5771, 6141, 6547, 6697, 6637, 6633, 6645, 6598, 6353, 5951, 5614, 5379, 5089, 4650, 4119, 3573, 3058, 2640, 2381, 2223, 2048, 1857, 1683, 1519, 1413, 1438, 1703, 2164, 2686, 3216, 3803, 4583, 5426, 6212, 6935, 7361, 7461, 7473, 7445, 7429, 7485, 7357, 6849, 6105, 5352, 4722, 4172, 3661, 3242, 2910, 2629, 2403, 2285, 2248, 2200, 2082, 1934, 1881, 2082, 2567, 3205, 3923, 4644, 5200, 5628, 6095, 6578, 6887, 7054, 7265, 7379, 7255, 6996, 6710, 6420, 6116, 5762, 5366, 4919, 4343, 3642, 2953, 2381, 1974, 1713, 1564, 1492, 1447, 1456, 1640, 2070, 2715, 3473, 4266, 5095, 5915, 6695, 7528, 8251, 8488, 8230, 7778, 7348, 6950, 6546, 6019, 5344, 4692, 4182, 3766, 3363, 2952, 2598, 2376, 2245, 2160, 2090, 2035, 2041 };
-
- // 100*2*4+136*2*2+200*4=2148字节 -100*2*4-100*2*2=948字节
- float allPeak1[100] = { 0 };
- short allPeak1_index[100] = { 0 };
- short allPeak1_nums[3] = { 0 };
- float allPeak2[100] = { 0 };
- short allPeak2_index[100] = { 0 };
- short allPeak2_nums[3] = { 0 };
-
- short peak1_index[33] = { 0 };
- short peak2_index[33] = { 0 };
- float data[200] = { 0 };
-
- for (short i = 0; i < 4; i++)
- {
- short label = RunStateDetection(arr, data, peak1_index, peak2_index, allPeak1, allPeak1_index, allPeak1_nums, allPeak2, allPeak2_index, allPeak2_nums);
- printf("label: %d\n",label);
- }
-
- }
load_model.c
- #include<stdio.h>
- #include "opencv2/core/core.hpp"
- #include "opencv2/ml/ml.hpp"
- #include <cstdio>
- #include <vector>
- #include <iostream>
-
- using namespace std;
- using namespace cv;
- using namespace cv::ml;
-
-
- // n维vector转mat
- Mat vector2Mat(vector<vector<float>> src)
- {
- int feature_nums = int(src.size()*src[0].size());
- Mat test(1, feature_nums, CV_32FC1); // CV_64FC1 1*200
-
- for (int i = 0; i < src.size(); ++i) {
- for (int j = 0; j < src[0].size(); j++)
- {
- int index = i * src[0].size() + j;
- test.at<float>(0, index) = src[i][j];
- }
- }
- return test;
- }
-
- // 数据输入为vector
- int StateEstimate(vector<vector<float>> acc, vector<vector<float>> gyr, vector<float> ppg, cv::Ptr<cv::ml::RTrees> model)
- {
- // 挑出测试数据
- vector<vector<float>> all_data;
- vector<float> az;
- for (int i = 0; i < acc.size(); i++)
- {
- az.push_back(acc[i][2]);
- }
- all_data.push_back(az);
-
- // 数据转换,vector转mat
- Mat test_data;
- test_data =vector2Mat(all_data);
-
- // 判断测试数据的特征维度是否正确,不正确返回-2
- if (test_data.cols != 200)
- {
- return -2;
- }
-
- // 模型预测
- cv::Mat res;
- model->predict(test_data, res);
-
- // 预测结果判断是否为空
- if (res.empty()) {
- return -1;
- }
-
- // 输出动作分类情况:-1-预测empty,-2-测试数据特征维度错误,0-非跑步,2-跑步
- int action = (int)(res.at<float>(0, 0));
- if (action==2)
- {
- return 2;
- }
- return 0;
- }
-
- int main() {
-
- 定义数据
- vector<vector<float>> acc;
- for (int i = 0; i < 200; i++)
- {
- vector<float>data;
- for (int j = 0; j < 3; j++)
- {
- data.push_back(i * 3 + j);
- }
- acc.push_back(data);
- }
-
- vector<vector<float>> gyr;
- for (int i = 0; i < 200; i++)
- {
- vector<float>data;
- for (int j = 0; j < 3; j++)
- {
- data.push_back(i * 3 + j);
- }
- gyr.push_back(data);
- }
-
- vector<float> ppg;
- for (int i = 0; i < 200; i++) {
- ppg.push_back(i);
- }
-
- // 模型加载
- cv::Ptr<cv::ml::RTrees> model = cv::ml::RTrees::load("svm-az.xml");
-
- // 模型预测:-1-预测empty,-2-测试数据特征维度错误,0-静止 ,1-走路
- int pred=StateEstimate(acc, gyr, ppg, model);
- std::cout << "预测结果为:" << pred << std::endl;
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。