임펄스(Impluse) 노이즈 제거를 위한 median filter c source code

본 글은 임펄스(Impluse) 노이즈가 있는 신호에서 임펄스 노이즈를 제거하기 위한 median filter대한 내용을 싣고 있다.

임펄스 노이즈는 짧은 시간 외부 환경의 영향으로 발생하는 충격성 잡음이며, 아래 그림의 예처럼 sin파에 큰 값으로 튀는 잡음이 발생하는 것을 말한다. 

신호 처리에서 임펄스 노이즈 제거를 위한 여러 방법이 존재하며, 영상처리 분야에서도 slat and pepper noise-영상의 최대값(0xff)과 최소값(0x00)으로 이루어진 잡음-로 알려진 임펄스 노이즈를 제거하기 위한 많은 방법들이 존재한다.
본 글은 그 중에 구현이 간단한 중간값 필터(median filter)에 대해 알아보았다. 
Median filter는 연속된 신호에서 특정 구간 윈도우내의 데이터를 크기 순으로 정렬해 그중 가운데 값을 대표 값으로 사용하는 필터이다. 
만약 임펄스 노이즈 ‘255’가 있는 데이터 [10, 255, 8, 11, 13]가 있다면, 데이터를 크기순으로 정렬하면 [8,10,11,13,255]이 되고, 중간 값은 11이 되며 이 구간의 대표 값은 11이 된다. 이렇게 하면 임펄스 노이즈 100은 사라지게 된다.
이 방법을 이용한 예제 소스는 아래와 같다.

//  qsort를 사용해 중간 값을 찾는 코드 
int compare(const void *f1, const void *f2)
{
return (*(double*)f1 > *(double*)f2) ? 1 : -1;
}

double get_qsort_median(double *data, int n)
{
if (!data) return 0;

qsort(data, n, sizeof(double), compare);
return data[n / 2];
}

// loop를 돌며 데이터를 정렬하여 중간 값을 찾는 코드
double get_median(double *data, int n)
{

#define swap(a,b) {double temp = a;a=b;b=temp;}
int i = 0;
int j = 0;
if (!data) return 0;

i = n - 1;
while (i > 0)
{
j = 0;
while (j < i)
{
if (data[j] > data[j + 1]) swap(data[j], data[j + 1]);
j++;
}

i--;
}
return data[n / 2];
}

int median_filter(double *in, double *out, int n)
{
#define window_size 3
double temp[window_size] = { 0, };
int i = 0;

if (!in || !out || n < window_size)
return -1;

for (i = window_size / 2; i < n - window_size / 2; i++)
{
memcpy(temp, &in[i - window_size / 2], window_size * sizeof(double));
out[i] = get_qsort_median(temp, window_size);
}

return 0;
}

위의 구현된 코드를 사용해 임펄스 노이즈를 하면 아래와 같다. 검은색 점선이 임펄스 노이즈가 들어있는 신호이며, 붉은색 선이 노이즈가 제거된 신호이다. 임펄스 노이즈는 제거되었지만, 노이즈 부분 데이터는 약간의 왜곡이 남아있다.

 

[관련 포스트]

댓글

이 블로그의 인기 게시물

간단한 cfar 알고리즘에 대해

아두이노(arduino) 심박센서 (heart rate sensor) 심박수 측정 example code

쉽게 설명한 파티클 필터(particle filter) 동작 원리와 예제

windows에서 간단하게 크롬캐스트(Chromecast)를 통해 윈도우 화면 미러링 방법

mkfs.fat Device or resource busy 에러 해결법