首页 > 编程语言 >滤波算法(移动平均滤波)

滤波算法(移动平均滤波)

时间:2024-08-07 17:58:19浏览次数:10  
标签:数据 double 滤波 算法 电压 折线图 移动 data

常见的滤波算法有:

限幅滤波法,中位值滤波算法,算术平均滤波法,移动平均滤波算法(也叫递推平均滤波算法),中位值平均滤波算法等等。

       服务器实时接收硬件传送过来的实时温度,实时浓度,实时电压,实时电流等实时数据时,通常会出现将异常的数据传送过来,比如电压,当实时接收硬件检测电动车电池电压时,会突然出现一些异常数据:比如正常电压数据值在1.5V-3.3V之间,突然电动车一刹车或者出现异常情况,电压一宿啊就变成3.3V以上或者1.5V以下,甚至出现了负数,这时,折线图现显示的实时电压数据图就会没有规律,不符合常识,也就是折现一下上一下下,这时有些题目就会要求对硬件传送过来的数据进行处理,并在图中展示出来。

     当题目要求使用滤波算法时,这时需要注意的问题是:

     1.展示折线图时需要用到两个折线图。一个用来展示数据未处理时的变化趋向,一个用来展示处理后的变化趋向。

      2.当接受硬件传送过来的实时数据时,对于那些异常的数据,也要存入数据库中。

      3.展示折线图时也可以用一个折线图,不过对于处理前的数据和处理后的数据可以用两种比较明显区分的颜色来代替。

接下来我将根据实时电压,来使用移动平均滤波算法,用一个折线图表示。具体如下:

  (1)首先我使用的任然是前后端不分离,对于硬件传送过来的数据帧,我首先在后端写了一个方法来对数据帧进行处理,然后对接收的数据根据情况进行处理:

@Component
public class Method {
    static double vs = 0;//定义一一个全局变量--用来表示前一个电压值
    static double avgs = 2.0;//平均值定义一个-----参考值
    static double value = 1;//设置电压的差值----1.5-2.5之间
    static double before=0.0;//表示前一个电压值
 
    public void addressMessage(String text) throws IOException, InterruptedException {
//这里表示处理从硬件那边发送过来的数据帧方法
              if (text.startsWith("SDNData")) {
              //数据帧格式--具体看硬件那边如何定义
//假如硬件那边发送过来的数据帧为:SDNData:V:2.3T
            
            LocalDateTime localDateTime = LocalDateTime.now();
            String time = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
               String currentv=text.substring(10,14);
                V v = new V();//创建一个对象---与数据库相关
                double v = Double.parseDouble(currentV); // 当前电压
                // 根据电压范围进行处理
                if (v >= 0 && v <= 3) {
                    // 当电压在0到3之间时
                    if (Math.abs(v - before) > 0.3) {
                        // 如果当前电压与前一个电压的差大于0.3,则进行滤波处理
                        double filteredV = AverageFilter(currentv, before2, 5);
                        before2 = filteredV; // 更新前一个值
                        v.setV(String.valueOf(currentv));//保留当前电压值
                        v.setP2(String.valueOf(filteredV));//过滤后的值
                    } else {
                        // 差小于等于0.3时,保留当前值
                        before = currentv; // 更新前一个值为当前值
                        v.setV(String.valueOf(currentv));
                        v.setP(String.valueOf(currentv));
                    }
                } else {
                    // 当电压超出0到3的范围时,直接进行滤波处理
                    double filteredV =AverageFilter(v, before, 5);
                    before = filteredV; // 更新前一个值
                    v.setP(String.valueOf(filteredV));//过滤后的值
                    v.setV(String.valueOf(v));
                }
                v.setTime(time); // 设置时间
                // 存入数据库
                vMapper.insert(v);
            }
       
    public double AverageFilter(double currentValue, double previousAverage, int windowSize) {
        // 实现移动平均滤波逻辑
        // windowSize 是滑动窗口的大小,可以根据需求调整
        //currentValue表示当前电压    previousAverage表示前一次的平均值  windowSize表示窗口的大小决定平均的范围
        double alpha = 2.0 / (windowSize + 1); // 平滑因子,根据实际情况调整
        return previousAverage + alpha * (currentValue - previousAverage);
    }

}

注意:在我建立的数据库中,在为data的表中有v和p还有time这三个字段,v代表未被处理的原始数据,p代表经过滤波处理之后的数据,time表示接收每一条数据的时间。

(2)前端折线图展示

其中蓝色表示原始数据,红黄色表示过滤之后的数据

(3)前端代码如下所示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>折线图</title>
    <!-- 引入 ECharts -->
    <script src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script>
    <!-- 引入 Bootstrap 样式 -->
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .chart-container {
            margin-bottom: 20px;
            border: 1px solid #ddd;
            padding: 10px;
        }
    </style>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-lg-6">
            <div id="实时电压折线图" class="chart-container" style="height: 300px;"></div>
          
        </div>

</div>
<script>
    // 初始化图表
    var myChart = echarts.init(document.getElementById('实时电压折线图'));
 
    //涉及多个折线图可以将其放一块---还有导入导出
    // 配置项
    var option = {
        title: {
            text: '实时电压折线图'
        },
        xAxis: {
            type: 'category',
        },
        yAxis: {
            type: 'value',
            min:-1.5,
            max:3.5,

        },
        tooltip: {
            trigger: 'axis', // 设置触发类型为坐标轴触发
            axisPointer: {
                type: 'cross' // 十字准星指示器,显示在坐标轴上
            }
        },
        series: [
            {
                name: '电池电压',
                data: [],
                type: 'line',
                color:'blue',
                smooth:true
            },
            {
                name: '有效电池电压',
                data: [],
                type: 'line',
                color:'red'
            }
        ]
    };
   
    // 使用配置项显示图表
    myChart.setOption(option);
    // 生成数据
    function fetchData() {
        fetch('http://localhost:8080/mysql/getAllHistory')
            .then(response => response.json())
            .then(data => {
                // 只取最新的10条记录
           //     data = data.slice(-10);
                var timeData = [];
                var VData = [];
                var PData = [];
                data.forEach(item => {
                    timeData.push(item.time);  // 时间
                   VData.push(item.v);  //
                    PData.push(item.p);  //
                });
                // 更新图表数据
                myChart.setOption({
                    xAxis: {
                        data: timeData
                    },
                    series: [
                        {
                            name: '实时电池电压',
                            data: VData
                        },
                        {
                            name: '有效电池电压',
                            data: PData
                        }
                    ]
                });
            })
            .catch(error => console.error('Error fetching data:', error));
    }
    // 初次加载数据
    fetchData();
    // 定期获取数据
    setInterval(fetchData, 1000);  // 每隔5秒钟获取一次数据
  }
  
</script>
</div>
</body>
</htm

(4)后端数据库代码如下:

1.controller层代码

@RestController
@CrossOrigin(origins = "http://localhost:63342")
@RequestMapping("/mysql")
public class VController {
    @Autowired
    private VService vService;
    @Autowired
    private VMapper vMapper;
    @GetMapping("/getAllHistory")
    public List<V> getAllHistory() {
        List<V> allHistory = vService.getAllHistory();
        V v= allHistory.get(0);
        return vService.getAllHistory();
    }

2.service层代码

public interface VService extends IService<V> {
    List<V> getAllHistory();
}

3.service实现类代码

@Service
public class VServiceImpl extends ServiceImpl<VMapper, V>
    implements VService{
    @Autowired
    private VMapper vMapper;

    @Autowired
    public VServiceImpl(VMapper vMapper) {
        this.vMapper = vMapper
        ;
    }
    @Override
    public List<V> getAllHistory() {
        QueryWrapper wrapper=new QueryWrapper<>();
        List<V> vs = vMapper.selectList(null);
        return vs;
    }
}

如运行上面代码有错误,可以在评论区指出错误或者私聊我

标签:数据,double,滤波,算法,电压,折线图,移动,data
From: https://blog.csdn.net/m0_74809043/article/details/140965136

相关文章

  • 泛微OA移动端在公网IP变更和无法打开Install.do界面下修改插件库地址(122,128报错)
    事情起因因为公司搬迁,公网IP变更,服务器搬迁时未提前调整好泛微oa服务器的IP,但是旧地址仍留有主路由可以使用。发现问题移动端无法正常连接,/install.do的界面也无法打开,无法进入修改插件库服务器IP的页面联系了技术,技术表示/install.do无法打开的话也无能为力(因为公司维护费断......
  • kmp算法(c++)
    kmp算法的简单介绍从主串中快速找到与要找的串的相同位置如果使用暴力算法去求解这个问题,时间复杂度为O(i*j)=>很大kmp算法则是对这类问题的优化因整理过于麻烦,,详细的介绍可以参照这篇博客,,花时间看完就明白了,写的很棒!!!kmp算法详细介绍下面是自己学习的一些注意的地......
  • 四、神经网络(深度学习算法)
    4.1认识神经网络必要性当特征值只有两个时,我们仍可以用之前学过的算法去解决但当特征值很多,且含有很多个多次多项式时,用之前的算法就很难解决了例子:图像感知Recogonitionimage计算机识别汽车是靠像素点的亮度值  神经网络做法:4.2如何在神经网络上推理4.2.1......
  • 代码随想录算法训练营day06|242.有效的字母异位词,349.两个数组的交集,202.快乐数,1.两数
    242.有效的字母异位词题目链接:https://leetcode.cn/problems/valid-anagram/description/我的代码:classSolution{public:boolisAnagram(strings,stringt){if(s.size()==t.size()){intrecord[26]={0};for(inti=0;i......
  • 路径规划算法之Dijistra算法、A*算法
    引言记录一下这段时间了解到的路径规划算法,并进行代码的实现目前主流的路径规划算法可以分为:基于采样,如RRT、RRT*、PRM基于节点,如Dijistra、A、D基于数学模型,如MILP、NLP基于生物启发式,如NN、GN多融合,如PRM-NodebasedDijistraalgorithm问题描述Dijistra算法主要......
  • 数组的算法
    数组的算法目录数组的算法1.数组排序2.数组查找3.数组求和、求最大值和最小值4.数组反转5.数组乱序6.数组复制7.数组去重1.数组排序冒泡排序:通过重复遍历要排序的数组,比较相邻元素的大小,并在必要时交换它们的位置,直到整个数组排序完成。冒泡排序的时间复杂度为O(n^2)......
  • kmp算法模板
    模板//pi代表前缀函数 //pi[i]:s[0~i]的最长匹配真前后缀长度 vecotr<int>pi(str.size()); //求前缀函数 for(inti=1;i<str.size();i++){ intlen=pi[i-1];//前一个值的pilen是我们想要找到的一个长度值 while(len!=0&&str[i]!=str[len]){//不匹配时,......
  • 【数据结构与算法】删除循环队列中第k个元素的算法 C++实现(循环队列+模运算)
    数组a[MaxSize]用作一个循环队列,front指向循环队列中队头元素的前一个位置,rear指向队尾元素的位置。设计删除队列中第k个元素的算法。思路首先,判断kkk是否在有效范围内......
  • 【数据结构与算法】在循环队列中第k个元素之后插入元素的算法 C++实现(循环队列+模运算
    数组a[MaxSize]用作一个循环队列,front指向循环队列中队头元素的前一个位置,rear指向队尾元素的位置。设计在队列中第k个元素之后插入item的算法。思路首先,检查输入的位置k是否在合理的范围内,即1到queueSize(Q)(包含两端)。如果k在这个范围外,那么返回ERROR。然后,计......
  • 算法力扣刷题记录 六十八【131.分割回文串】
    前言回溯章节第六篇。切割问题。记录六十八【131.分割回文串】。一、题目阅读给你一个字符串s,请你将s分割成一些子串,使每个子串都是回文串。回文串指字符串从前读和从后读一样。返回s所有可能的分割方案。示例1:输入:s="aab"输出:[["a","a","b"],["aa","b"]]......