中位值滤波法

        中位值滤波算法是一种典型的非线性滤波器,它运算简单,在滤除脉冲噪声的同时可以很好地保护信号的细节信息,应用比较广泛,特别适用于会偶然出现异常值的系统。

一、原理

       连续采集N个周期(N取奇数)的数据,去掉N个周期数据中的最大值和最小值,取剩下的数据的中位值。

二、优势

        能过滤因偶然因素引起的波动干扰,对温度、液位的变化缓慢的被测参数有良好的滤波效果。

三、缺点

        反应速度慢、滞后,对流量、速度等快速变化的数据不宜使用该方法。

四、示例代码
 

#include <stdio.h>
#include <stdlib.h>

/*随机范围*/
#define RAND_VALUE_M 295
#define RAND_VALUE_N 305
/*滤波缓冲大小 2n+1 */
#define FILTER_N (2*8+1)
/*定义滤波数据类型*/
typedef	int filter_type;
/*定义最大允许误差*/
filter_type filter_buf[FILTER_N];

/*限幅滤波初始化函数*/
void limit_filter_init(void);
/*滤波函数声明*/
filter_type limit_filter(filter_type new_value);
/*获取新数据函数声明*/
filter_type get_new_value(void);

int main(void)
{
    filter_type new_value = 0, effective_value = 0;

    limit_filter_init();
    for (int index = 0; index < 32; index++) {
        new_value = get_new_value();
        effective_value = limit_filter(new_value);
        printf("new_value,%d,effective_value,%d\n", new_value, effective_value);
    }

    return 0;
}

filter_type get_new_value(void)
{
    return RAND_VALUE_M + rand() % (RAND_VALUE_N - RAND_VALUE_M + 1);
}

/*限幅滤波初始化函数*/
void limit_filter_init(void)
{
    int index = 0;

    for(index = 0; index < FILTER_N; index++) {
        filter_buf[index] = get_new_value();
    }

    return;
}

void add_nwe_value_to_filter_buf(filter_type new_value)
{
    static int index = 0;

    index = (index + 1) % FILTER_N;
    filter_buf[index] = new_value;
    return;
}

/*限幅滤波函数*/
filter_type limit_filter(filter_type new_value)
{
    int i, j;
    filter_type filter_temp;
    
    add_nwe_value_to_filter_buf(new_value);
    // 采样值从小到大排列(冒泡法)
    for(j = 0; j < FILTER_N - 1; j++) {
        for(i = 0; i < FILTER_N - 1 - j; i++) {
            if(filter_buf[i] > filter_buf[i + 1]) {
                filter_temp = filter_buf[i];
                filter_buf[i] = filter_buf[i + 1];
                filter_buf[i + 1] = filter_temp;
            }
        }
    }
    return filter_buf[(FILTER_N - 1) / 2];
}

五、滤波效果

0b2c4ed1bc4a4c83b83ee776bb7b3886.png

 

56c51ddc2a2f48709dd515a5183303d6.png

 

 

### 中位值滤波法 (Median Filtering) 的 C 语言实现 **中位值滤波法**是一种常见的图像处理和信号处理技术,用于去除噪声。它通过将每个像素点的灰度值替换为其邻域内的中位数来达到平滑效果。相比均值滤波等其他方法,它可以更好地保留边缘信息。 #### 算法步骤: 1. **选择窗口大小**:通常是一个奇数尺寸的方形窗口(如 3x3、5x5),该窗口会在整个图像上移动。 2. **提取邻域内元素**:对于每一个中心位置,获取其周围所有元素构成的新数组。 3. **排序并取中间值**:对该新数组按升序排列,并取出排在最中央的那个数值作为当前像素的新值。 4. **更新原图对应坐标处的颜色分量**。 5. **继续下一个像素直到完成整幅图片遍历**。 下面是具体的 `C` 实现代码示例: ```c #include <stdio.h> #include <stdlib.h> // 定义函数声明 void medianFilter(int *inputImg, int width, int height); int main() { // 示例输入矩阵(假设已经读入) const int WIDTH = 5; const int HEIGHT = 5; /* 初始化一个测试数据集 */ int inputImage[HEIGHT][WIDTH] = { {80, 90, 70, 60, 10}, {85, 75, 95, 85, 90}, {90, 80, 100, 70, 85}, {60, 70, 80, 90, 80}, {70, 80, 90, 100, 95} }; printf("原始图像:\n"); for(int i=0; i<HEIGHT; ++i){ for(int j=0; j<WIDTH; ++j){ printf("%d ", inputImage[i][j]); } putchar('\n'); } // 调用中值滤波器函数 medianFilter((int *)inputImage, WIDTH, HEIGHT); return 0; } /** * @brief 对给定的一维数组进行快速排序 */ static void quickSort(int arr[], int low, int high) { if(low<high){ int pi = partition(arr,low,high); quickSort(arr,low,pi-1); quickSort(arr,pi+1,high); } } /** Partition function used in Quick Sort Algorithm */ static int partition(int arr[], int low, int high) { int pivot = arr[high]; int i=(low - 1); for(int j = low;j <= high-1;++j){ if(arr[j]<pivot){ ++i; swap(&arr[i],&arr[j]); } } swap(&arr[i + 1], &arr[high]); return(i + 1); } static inline void swap(int *a, int *b){ (*a)^=*b; (*b)=(*a)^(*b); (*a)=(*a)^(*b); }; // 中值滤波算法主程序入口 void medianFilter(int *img, int w, int h) { #define WINDOW_SIZE 3 int windowBuffer[WINDOW_SIZE * WINDOW_SIZE]; // 缓存窗口内容的空间 // 遍历每个像素点 for (int y = 1; y < h - 1; ++y) { for (int x = 1; x < w - 1; ++x) { // 提取指定区域的所有相邻像素到缓冲区 for (int ky = -1; kx <= 1; ++kx) { windowBuffer[(ky + 1)*WINDOW_SIZE+(kx + 1)] = img[(y + ky) * w + (x + kx)]; } } // 对于缓存的数据做快排操作求解出其中位数 quickSort(windowBuffer, 0, sizeof(windowBuffer)/sizeof(windowBuffer[0]) - 1); // 使用找到的中位数替代原来的像素强度值 *(img+y*w+x)=(windowBuffer[sizeof(windowBuffer)/2]); } } // 打印结果图像 puts("\n经过中值滤波后的图像:"); for(int row=0;row<h;row++){ for(int col=0;col<w;col++) printf("%d\t",*(img+row*w+col)); putchar('\n'); } } ``` 请注意这只是一个简单的演示版本,在实际应用时可能需要考虑边界条件和其他优化措施。 --- 为了简化上述代码以便更容易理解核心思想,这里省略了一些复杂的错误检查机制以及对边界的特殊处理;真实的项目里建议添加额外保护逻辑以防止越界访问等问题的发生。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值