Java均值滤波思想降折线噪点
项目场景:
项目需求:PLC共采集8000个点,监测8000个点位内的产品厚度波动。
问题描述
8000个点采集下来,检测点和预想值出现了偏差,出现这些点会使整个产品被系统判定为次品,从而报废。以下为次品图:
其实这个产品是没有问题的,所以要做滤波处理,将这些点为的值处理为正常值。
方案:
看了很多滤波方式,大多都是处理图像,想要改造费时费力,最终决定使用简单点儿的均值滤波。
代码:
/ * @param dataList 目标点 * @param tag 窗口大小 tag越大折线越平滑 * @return 返回处理后新的点位数组 */private static List Meanss(List dataList, int tag) {//定义返回新的点位数组 List newPoints = new ArrayList(); try { if (dataList.size() < tag || dataList.isEmpty()) throw new Exception("目标数组内容异常"); if (tag % 2 != 0) throw new Exception("目标参数异常"); } catch (Exception e) { e.printStackTrace(); } //判断是否偶数 if (tag % 2 == 0) { //从tag / 2 开始赋值 int before = tag / 2; //到tag / 2 结束赋值 int length = dataList.size() - (tag / 2); //将tag / 2 之前的值不做运算,存入新数组 for (int j = 0; j < before; j++) { newPoints.add(dataList.get(j)); } //前后(tag/2)位参与计算不赋值 for (int i = before; i < length; i++) { //获取需要求平均值的子数组 List tags = dataList.subList(i - before, i + before); //使用reduce计算BigDecimal平均值 BigDecimal avgNum = tags.stream().reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(tag), 1); newPoints.add(avgNum); } //后 tag/2 个点位不计算,原值加入 for (int k = length; k < dataList.size(); k++) { newPoints.add(dataList.get(k)); } } return newPoints; }
过滤后结果
过滤前:
过滤后:
完美解决