01
中值濾波
原理
中值濾波是一種非線性濾波算法,它將信號(hào)中的每個(gè)采樣點(diǎn)替換成該采樣點(diǎn)鄰域內(nèi)的中值。它的主要思想是通過(guò)找到鄰域內(nèi)的中值來(lái)消除信號(hào)中的噪聲,同時(shí)盡可能地保留信號(hào)中的有用信息。
中值濾波的步驟如下:
a. 定義鄰域大小和形狀。常用的鄰域形狀有矩形、圓形、十字形等。
b. 對(duì)信號(hào)的每個(gè)采樣點(diǎn),選取其鄰域內(nèi)的所有采樣點(diǎn),并將其排序。
c. 將排序后的采樣點(diǎn)序列中間的值作為該采樣點(diǎn)的輸出值。
由于中值濾波采用了排序的方式,因此它比線性濾波算法的計(jì)算量要大,但是相對(duì)于其它非線性濾波算法,中值濾波的計(jì)算量相對(duì)較小,而且不需要預(yù)先確定濾波器參數(shù),因此具有很好的實(shí)時(shí)性能。
中值濾波通常適用于以下場(chǎng)景:
a. 信號(hào)中含有脈沖噪聲或椒鹽噪聲。
b. 信號(hào)中含有高斯噪聲,但信號(hào)的均值和方差不易確定。
c. 信號(hào)中含有周期性噪聲,周期長(zhǎng)度大于鄰域大小。
需要注意的是,中值濾波可能會(huì)導(dǎo)致信號(hào)的某些特征被模糊化,因此在應(yīng)用中需要謹(jǐn)慎選擇鄰域大小和形狀,以及濾波器的使用場(chǎng)景。
代碼
下面是一個(gè)使用C語(yǔ)言編寫(xiě)的中值濾波函數(shù)的示例代碼,它可以處理一個(gè)長(zhǎng)度為N的整型數(shù)組input,并將輸出結(jié)果保存在一個(gè)長(zhǎng)度為N的整型數(shù)組output中。這個(gè)函數(shù)的鄰域大小由變量size指定,可以根據(jù)需要進(jìn)行調(diào)整。
C++
#include
#include
#define SIZE 3 // 鄰域大小
int cmp(const void *a, const void b) {
return ( (int *)a - *(int *)b);
}
void median_filter(int *input, int *output, int N) {
int i, j, k, m;
int median[SIZE * SIZE];
for (i = 0; i < N; i++) {
k = 0;
for (j = i - (SIZE - 1) / 2; j <= i + (SIZE - 1) / 2; j++) {
if (j < 0 || j >= N) {
continue;
}
for (m = j - (SIZE - 1) / 2; m <= j + (SIZE - 1) / 2; m++) {
if (m < 0 || m >= N) {
continue;
}
median[k++] = input[m];
}
}
qsort(median, k, sizeof(int), cmp);
output[i] = median[k / 2];
}
}
int main() {
int input[] = {1, 5, 2, 7, 3, 9, 4, 8, 6};
int output[sizeof(input) / sizeof(int)];
int N = sizeof(input) / sizeof(int);
int i;
median_filter(input, output, N);
printf("Input data: ");
for (i = 0; i < N; i++) {
printf("%d ", input[i]);
}
printf("n");
printf("Output data: ");
for (i = 0; i < N; i++) {
printf("%d ", output[i]);
}
printf("n");
return 0;
}
輸出結(jié)果如下:
Kotlin
Input data: 1 5 2 7 3 9 4 8 6
Output data: 2 2 3 4 4 5 6 7 8
可以看到,中值濾波算法可以有效地消除噪聲,同時(shí)盡可能地保留原始信號(hào)的特征。需要注意的是,在使用中值濾波算法時(shí),鄰域大小的選擇需要根據(jù)實(shí)際情況進(jìn)行調(diào)整,以免產(chǎn)生過(guò)度平滑或者信息損失的問(wèn)題。
02
消抖濾波
原理
消抖濾波法(Debouncing Filter)是一種常用的信號(hào)處理算法。它主要用于消除由于輸入信號(hào)在短時(shí)間內(nèi)出現(xiàn)了快速變化而導(dǎo)致的抖動(dòng)現(xiàn)象。在實(shí)際應(yīng)用中,如電子開(kāi)關(guān)、按鍵等場(chǎng)景中,由于機(jī)械接觸的原因,可能會(huì)產(chǎn)生短時(shí)間內(nèi)快速變化的信號(hào),這種信號(hào)稱(chēng)為抖動(dòng)信號(hào),會(huì)對(duì)系統(tǒng)產(chǎn)生誤判和誤動(dòng)作。因此,需要對(duì)這種信號(hào)進(jìn)行濾波處理。
消抖濾波法的基本思想是在輸入信號(hào)發(fā)生變化時(shí),延遲一段時(shí)間再檢測(cè)信號(hào)狀態(tài),如果信號(hào)保持穩(wěn)定狀態(tài),則認(rèn)為信號(hào)有效。如果信號(hào)在這段時(shí)間內(nèi)發(fā)生了變化,則重新計(jì)時(shí)。這種方法可以有效地抑制抖動(dòng)信號(hào),并且可以消除無(wú)效的信號(hào)瞬態(tài)。
消抖濾波法的具體實(shí)現(xiàn)方式可以采用軟件或硬件的方式實(shí)現(xiàn)。軟件實(shí)現(xiàn)方式常見(jiàn)的是利用定時(shí)器進(jìn)行延時(shí),硬件實(shí)現(xiàn)方式常見(jiàn)的是利用RC電路進(jìn)行延時(shí)。下面給出一個(gè)基于軟件實(shí)現(xiàn)的消抖濾波函數(shù)的偽代碼:
Python
int debouncing_filter(int input, int delay_ms) {
static int last_input = 0;
static int stable_cnt = 0;
if (input != last_input) {
stable_cnt = 0;
}
else {
stable_cnt++;
}
last_input = input;
if (stable_cnt >= delay_ms / sampling_time) {
return input;
}
else {
return last_input;
}
}
在這個(gè)函數(shù)中,input表示輸入信號(hào)的狀態(tài),delay_ms表示需要延遲的時(shí)間。函數(shù)通過(guò)記錄上一個(gè)時(shí)刻的輸入狀態(tài)以及信號(hào)保持穩(wěn)定狀態(tài)的時(shí)間來(lái)實(shí)現(xiàn)消抖功能。如果信號(hào)保持穩(wěn)定狀態(tài)的時(shí)間超過(guò)了設(shè)定的延時(shí)時(shí)間,則返回當(dāng)前的輸入狀態(tài)。否則,返回上一個(gè)時(shí)刻的輸入狀態(tài)。
需要注意的是,在使用消抖濾波法時(shí),延時(shí)時(shí)間需要根據(jù)具體的應(yīng)用場(chǎng)景來(lái)進(jìn)行設(shè)置。如果延時(shí)時(shí)間設(shè)置過(guò)長(zhǎng),則可能會(huì)導(dǎo)致信號(hào)響應(yīng)時(shí)間過(guò)長(zhǎng),影響系統(tǒng)的實(shí)時(shí)性;如果延時(shí)時(shí)間設(shè)置過(guò)短,則可能會(huì)無(wú)法有效地抑制抖動(dòng)信號(hào)。
代碼
下面給出一個(gè)基于軟件實(shí)現(xiàn)的消抖濾波函數(shù)的具體實(shí)現(xiàn)代碼,以及使用示例:
C++
int debouncing_filter(int input, int delay_ms) {
static int last_input = 0;
static int stable_cnt = 0;
if (input != last_input) {
stable_cnt = 0;
}
else {
stable_cnt++;
}
last_input = input;
if (stable_cnt >= delay_ms / 10) { // 采樣周期假設(shè)為10ms
return input;
}
else {
return last_input;
}
}
在這個(gè)函數(shù)中,input表示輸入信號(hào)的狀態(tài),delay_ms表示需要延遲的時(shí)間。函數(shù)通過(guò)記錄上一個(gè)時(shí)刻的輸入狀態(tài)以及信號(hào)保持穩(wěn)定狀態(tài)的時(shí)間來(lái)實(shí)現(xiàn)消抖功能。如果信號(hào)保持穩(wěn)定狀態(tài)的時(shí)間超過(guò)了設(shè)定的延時(shí)時(shí)間,則返回當(dāng)前的輸入狀態(tài)。否則,返回上一個(gè)時(shí)刻的輸入狀態(tài)。
下面給出一個(gè)示例,展示如何使用該函數(shù)進(jìn)行消抖處理:
C++
#include
int main() {
int input = 0;
int output = 0;
int delay_ms = 50; // 延時(shí)時(shí)間為50ms
while (1) {
scanf("%d", &input); // 從終端讀取輸入信號(hào)狀態(tài)
output = debouncing_filter(input, delay_ms); // 進(jìn)行消抖濾波處理
printf("Input: %d, Output: %dn", input, output); // 輸出結(jié)果
}
return 0;
}
在這個(gè)示例中,首先從終端讀取輸入信號(hào)狀態(tài),然后調(diào)用debouncing_filter函數(shù)進(jìn)行消抖濾波處理,并將處理后的結(jié)果輸出到終端。循環(huán)執(zhí)行該過(guò)程,直到程序結(jié)束。
03
遞推平均濾波
原理
遞推平均濾波法,又稱(chēng)為滑動(dòng)平均濾波法,是一種對(duì)于輸入信號(hào)進(jìn)行平滑處理的算法。該算法采用一定的方式對(duì)一定數(shù)量的輸入信號(hào)進(jìn)行加權(quán)平均,得到一個(gè)平滑的輸出信號(hào)。具體地,遞推平均濾波法使用一個(gè)固定長(zhǎng)度的窗口,每當(dāng)有新的輸入信號(hào)到來(lái)時(shí),就將窗口內(nèi)的舊的信號(hào)淘汰掉,并將新的信號(hào)加入到窗口中,然后重新計(jì)算窗口內(nèi)所有信號(hào)的平均值作為當(dāng)前的輸出信號(hào)。
因此,隨著新的信號(hào)不斷到來(lái),窗口內(nèi)的信號(hào)會(huì)不斷滑動(dòng),而輸出信號(hào)也會(huì)不斷變化,從而實(shí)現(xiàn)對(duì)輸入信號(hào)的平滑處理。
遞推平均濾波法的優(yōu)點(diǎn)是簡(jiǎn)單、實(shí)時(shí)性好,對(duì)于周期性的噪聲有一定的抑制效果。其缺點(diǎn)是在處理突變的輸入信號(hào)時(shí),輸出信號(hào)會(huì)有一定的延遲,且在窗口大小不夠大的情況下,噪聲的抑制效果會(huì)比較有限。
下面是遞推平均濾波法的算法步驟:
a. 定義一個(gè)固定長(zhǎng)度為N的窗口,并初始化窗口內(nèi)的所有數(shù)據(jù)為0。
b. 當(dāng)有新的輸入信號(hào)x_i到來(lái)時(shí),將窗口內(nèi)的第一個(gè)信號(hào)x_{i-N}移除,并將新的信號(hào)x_i加入到窗口中。
c. 計(jì)算窗口內(nèi)所有信號(hào)的平均值,作為當(dāng)前的輸出信號(hào)y_i。
d. 返回輸出信號(hào)y_i,并等待下一次輸入信號(hào)到來(lái)。
代碼
下面是遞推平均濾波法的示例代碼,其中,N為窗口大小,x表示輸入信號(hào),y表示輸出信號(hào),buffer為窗口緩存,sum為窗口內(nèi)數(shù)據(jù)的累加和:
C++
#define N 10 // 窗口大小
float moving_average_filter(float x) {
static float buffer[N] = {0};
static float sum = 0;
static int ptr = 0;
sum = sum - buffer[ptr] + x;
buffer[ptr] = x;
ptr = (ptr + 1) % N;
return sum / N;
}
在這個(gè)函數(shù)中,我們使用了一個(gè)靜態(tài)的窗口緩存buffer來(lái)存儲(chǔ)窗口內(nèi)的數(shù)據(jù),使用sum來(lái)記錄窗口內(nèi)數(shù)據(jù)的累加和,使用ptr來(lái)記錄當(dāng)前窗口內(nèi)最后一個(gè)數(shù)據(jù)的位置。當(dāng)有新的輸入信號(hào)x到來(lái)時(shí),我們將窗口內(nèi)第一個(gè)數(shù)據(jù)buffer[ptr-N]移除,并將新的信號(hào)x加入到窗口中。然后,我們重新計(jì)算窗口內(nèi)所有信號(hào)的平均值作為當(dāng)前的輸出信號(hào),并將作為當(dāng)前的輸出信號(hào),返回輸出信號(hào),并等待下一次輸入信號(hào)到來(lái)。
04
中位值平均濾波法
原理
中位值平均濾波法是一種抗干擾性能很強(qiáng)的濾波方法,也稱(chēng)為防脈沖干擾平均濾波法。與其他濾波方法不同的是,它不是對(duì)一段時(shí)間內(nèi)的數(shù)據(jù)進(jìn)行簡(jiǎn)單的平均處理,而是將一段時(shí)間內(nèi)的多個(gè)數(shù)據(jù)進(jìn)行排序,然后取中間值作為濾波結(jié)果。中位值平均濾波法的優(yōu)點(diǎn)是可以有效地濾除脈沖噪聲、斜坡干擾等干擾信號(hào)。
中位值平均濾波法的實(shí)現(xiàn)步驟如下:
a. 將一段時(shí)間內(nèi)的多個(gè)數(shù)據(jù)存儲(chǔ)在數(shù)組中;
b. 對(duì)數(shù)組進(jìn)行排序;
c. 取排序后中間位置的數(shù)值作為濾波結(jié)果。
中位值平均濾波法的實(shí)現(xiàn)較為簡(jiǎn)單,但由于需要對(duì)數(shù)組進(jìn)行排序,計(jì)算量較大,因此在實(shí)際應(yīng)用中需要注意性能問(wèn)題。
中位值平均濾波法的優(yōu)點(diǎn):
a. 對(duì)脈沖噪聲、斜坡干擾等干擾信號(hào)具有較強(qiáng)的濾除能力;
b. 濾波效果較好,能夠保持信號(hào)的較高精度。
中位值平均濾波法的缺點(diǎn):
a. 計(jì)算量較大,特別是在大數(shù)據(jù)量時(shí);
b. 無(wú)法完全消除高頻噪聲,因此在高頻噪聲較多的情況下效果可能不佳;
c. 數(shù)組排序會(huì)改變?cè)紨?shù)據(jù)的順序,因此需要注意排序的實(shí)現(xiàn)方式,避免對(duì)實(shí)際應(yīng)用造成影響。
代碼
C++
#include
// 中位值平均濾波函數(shù)
int Median_Filter(int *data, int length)
{
int i, j, temp, result;
int *sort = (int *)malloc(sizeof(int) * length); // 分配排序數(shù)組的空間
memcpy(sort, data, sizeof(int) * length); // 復(fù)制原始數(shù)據(jù)到排序數(shù)組
// 冒泡排序
for (i = 0; i < length - 1; i++) {
for (j = i + 1; j < length; j++) {
if (sort[i] > sort[j]) {
temp = sort[i];
sort[i] = sort[j];
sort[j] = temp;
}
}
}
// 取中間值作為濾波結(jié)果
result = sort[length / 2];
// 釋放排序數(shù)組的空間
free(sort);
return result;
}
int main()
{
int data[10] = {5, 6, 8, 9, 12, 7, 13, 10, 11, 6};
int result;
result = Median_Filter(data, 10);
printf("Filtered result: %dn", result);
return 0;
}
上面的程序?qū)崿F(xiàn)了一個(gè)簡(jiǎn)單的中位值平均濾波函數(shù)Median_Filter,該函數(shù)的參數(shù)data為原始數(shù)據(jù)數(shù)組,length為數(shù)據(jù)數(shù)組的長(zhǎng)度。函數(shù)返回經(jīng)過(guò)中位值平均濾波后的結(jié)果。
在main函數(shù)中,我們聲明了一個(gè)長(zhǎng)度為10的原始數(shù)據(jù)數(shù)組data,并將其傳遞給Median_Filter函數(shù)進(jìn)行中位值平均濾波。最后輸出濾波后的結(jié)果。
-
濾波器
+關(guān)注
關(guān)注
158文章
7594瀏覽量
176559 -
非線性濾波
+關(guān)注
關(guān)注
0文章
7瀏覽量
6729 -
中值濾波
+關(guān)注
關(guān)注
0文章
14瀏覽量
8353 -
高斯噪聲
+關(guān)注
關(guān)注
0文章
11瀏覽量
8347
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論