均值滤波算法及实现

均值滤波器的使用场景:

均值滤波器使用于处理一些如上述蓝色线的高斯噪声场景

红色曲线是经过均值滤波处理后的数据。主要因为均值滤波设置数据缓冲区(也即延时周期),使得测量值经过缓冲不会出现特别大的变化。

黄色曲线为高斯噪声,红色曲线为经过均值滤波处理后的数据。

如果想要更好的滤波效果:

  • 增加滤波和,也即往后多取几帧数据进行累加求和,再处以累加次数;
  • 嵌套使用均值滤波,也即用上一均值滤波输出作为本次滤波输入;
    均值滤波不适合处理类似橙色曲线的脉冲噪声的数据

蓝色曲线为经过均值滤波处理后的数据,虽然整体幅值降低了,但是如61-69区间,实际测量只在61附近出现一次突变,但很快下降正常,但经过均值滤波处理,虽然幅值被降低,但其实也没有达到理想,反而将突变脉冲以一个恒定的值持续了9s(累加次数,也即缓冲周期)。

目标脉冲值是0,未经过均值滤波处理在61s出现一较大突变,由于系统本身的阻尼等作用,系统实际不会产生太大的振荡,可能由于来的比较快,系统会微微抖一下就稳定。但如果使用均值滤波处理后,在61s处的尖峰脉冲硬是被拉长了9帧才退出,系统稳定性必定太差。因此脉冲信号噪声不适合用均值滤波,可以考虑使用低通滤波!


均值滤波作用

均值滤波是一种常见的图像处理技术,用于平滑图像中的噪声或细节。它的主要用途包括:

  1. 去除噪声:图像中的噪声是由于图像采集过程中的各种因素引入的不希望的干扰。均值滤波可以通过计算像素周围邻域内像素的平均值来平滑图像,并减少噪声的影响。

  2. 平滑图像:在某些情况下,图像中的细节过多或变化过于剧烈,可能会导致视觉上的不连续或不平滑感觉。均值滤波可以通过平均周围像素的值来减少这些细节,使图像更加平滑。

  3. 降低图像分辨率:在一些应用中,需要降低图像的分辨率以减少计算或存储的需求。均值滤波可以通过对图像进行平滑来实现降低分辨率的效果。

  4. 图像预处理:在某些图像处理任务中,如图像分割或边缘检测,均值滤波可以作为预处理步骤,帮助提取更准确的特征或边缘。

需要注意的是,均值滤波是一种简单且常用的滤波方法,但它可能会导致图像细节的模糊或平滑化。对于某些应用场景,可能需要考虑其他更高级的滤波技术,以在平滑图像的同时保留更多的细节信息。


均值滤波实现:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
 
double* weightedMeanFilter(double* input, int length, int windowSize, double* weights) {
    double* output = (double*)malloc(length * sizeof(double)); // 创建新数组
    int halfWindowSize = windowSize / 2;
    
    for (int i = 0; i < length; i++) {
        double weightedSum = 0.0;
        double weightSum = 0.0;
        
        for (int j = i - halfWindowSize; j <= i + halfWindowSize; j++) {
            if (j >= 0 && j < length) {
                weightedSum += input[j] * weights[j - (i - halfWindowSize)];
                weightSum += weights[j - (i - halfWindowSize)];
            }
        }
        
        output[i] = weightedSum / weightSum; // 计算加权平均值
    }
    
    return output;
}
 
int main() {
    double input[] = {1.2, 2.3, 3.4, 4.5, 5.6};
    int length = sizeof(input) / sizeof(input[0]);
    int windowSize = 3;
    
    double weights[] = {0.1, 0.6, 0.3}; // 示例权重系数数组
    
    double* output = weightedMeanFilter(input, length, windowSize, weights);
    
    printf("Input: ");
    for (int i = 0; i < length; i++) {
        printf("%.2f ", input[i]);
    }
    
    printf("\nOutput: ");
    for (int i = 0; i < length; i++) {
        printf("%.2f ", output[i]);
    }
    
    free(output); // 释放动态分配的内存
    
    return 0;
}
/*
Input: 1.20 2.30 3.40 4.50 5.60 
Output: 1.57 2.52 3.62 4.72 5.44
*/

增加权重系数可以使均值滤波更加灵活,以更好地适应不同的应用场景和需求。具体来说,增加权重系数的意义包括:

  1. 强调重要区域:通过调整权重系数,可以使某些像素在计算均值时具有更大的贡献。这样可以使均值滤波更加关注重要的区域,从而保留或突出这些区域的细节。例如,在人脸识别中,可以增加权重系数以突出人脸区域,以便更好地提取人脸特征。

  2. 抑制噪声或异常值:某些像素可能受到噪声或异常值的干扰,导致它们的值与周围像素明显不同。通过降低这些像素的权重系数,可以减少它们对均值的影响,从而抑制噪声或异常值的影响。

  3. 考虑空间相关性:在一些情况下,像素之间的空间关系对滤波结果的影响很大。通过调整权重系数以考虑像素之间的空间相关性,可以更好地保留图像的结构信息。例如,可以使用高斯加权系数来加权计算均值,以便更好地平滑图像并保留边缘。

  4. 自适应滤波:通过根据像素的特征或属性来动态调整权重系数,可以实现自适应滤波。这意味着不同的像素可以具有不同的权重,从而使滤波更加适应图像的局部特征。例如,可以根据像素的梯度值或纹理信息来调整权重系数,以实现更好的平滑效果。

总之,增加权重系数可以提供更多的灵活性和控制力,使均值滤波能够更好地适应不同的图像处理需求,并在平滑图像的同时保留重要的细节。

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
 
double* weightedMeanFilter(double* input, int length, int windowSize, double* weights) {
    double* output = (double*)malloc(length * sizeof(double)); // 创建新数组
    int halfWindowSize = windowSize / 2;
    
    for (int i = 0; i < length; i++) {
        double weightedSum = 0.0;
        double weightSum = 0.0;
        
        for (int j = i - halfWindowSize; j <= i + halfWindowSize; j++) {
            if (j >= 0 && j < length) {
                weightedSum += input[j] * weights[j - (i - halfWindowSize)];
                weightSum += weights[j - (i - halfWindowSize)];
            }
        }
        
        output[i] = weightedSum / weightSum; // 计算加权平均值
    }
    
    return output;
}
 
int main() {
    double input[] = {1.2, 2.3, 3.4, 4.5, 5.6};
    int length = sizeof(input) / sizeof(input[0]);
    int windowSize = 3;
    
    double weights[] = {0.1, 0.6, 0.3}; // 示例权重系数数组
    
    double* output = weightedMeanFilter(input, length, windowSize, weights);
    
    printf("Input: ");
    for (int i = 0; i < length; i++) {
        printf("%.2f ", input[i]);
    }
    
    printf("\nOutput: ");
    for (int i = 0; i < length; i++) {
        printf("%.2f ", output[i]);
    }
    
    free(output); // 释放动态分配的内存
    
    return 0;
}
/*
Input: 1.20 2.30 3.40 4.50 5.60 
Output: 1.57 2.52 3.62 4.72 5.44
*/

结果对比:


参考:

1、简单的均值滤波讲解(附代码)_哔哩哔哩_bilibili

2、https://www.cnblogs.com/faithlocus/p/17532226.html

相关推荐
莫叫石榴姐15 分钟前
数据科学与SQL:组距分组分析 | 区间分布问题
大数据·人工智能·sql·深度学习·算法·机器学习·数据挖掘
茶猫_1 小时前
力扣面试题 - 25 二进制数转字符串
c语言·算法·leetcode·职场和发展
肥猪猪爸3 小时前
使用卡尔曼滤波器估计pybullet中的机器人位置
数据结构·人工智能·python·算法·机器人·卡尔曼滤波·pybullet
readmancynn3 小时前
二分基本实现
数据结构·算法
萝卜兽编程4 小时前
优先级队列
c++·算法
盼海4 小时前
排序算法(四)--快速排序
数据结构·算法·排序算法
一直学习永不止步4 小时前
LeetCode题练习与总结:最长回文串--409
java·数据结构·算法·leetcode·字符串·贪心·哈希表
Rstln5 小时前
【DP】个人练习-Leetcode-2019. The Score of Students Solving Math Expression
算法·leetcode·职场和发展
芜湖_5 小时前
【山大909算法题】2014-T1
算法·c·单链表
珹洺5 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode