median filter를 사용하여 이미지의 salt and pepper noise 제거 예제 코드

본 글은 median filter를 사용하여 salt and pepper noise를 제거하는 예제 코드를 싣고 있다.

이전 “임펄스(Impluse) 노이즈 제거를 위한 median filter c source code”글에서 median filter로 신호에 발생한 임펄스 노이즈를 제거하는 예제를 본적이 있다.
이번에는 median filter를 사용하여 이미지의 slat and pepper noise를 제거해 보았다. 
위키피디아(https://en.wikipedia.org/wiki/File:Noise_salt_and_pepper.png)에서 다운 받은 이미지를 사용하기로 했다. 원리는 이전 글의 median filter와 동일하다. 다만 이미지 데이터 처리를 위해 데이터 형식이 int형으로 변형되었다.  다만 다운받은 테스트 이미지에 컬러가 없어서 컬러는 데이터는 고려하지 않았다. png파일은 24bits bitmap으로 변환하여 테스트하였다.

typedef int element_type;

int compare(const void *f1, const void *f2)
{
return (*(element_type*)f1 > *(element_type*)f2) ? 1 : -1;
}

element_type get_qsort_median(element_type*data, int n)
{
if (!data || n <= 0) return 0;

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


int get_pixels(unsigned char *in, int *out, RECT *rect, int stride, int bytesperpixel)
{
int x = 0;
int y = 0;
int n = 0;
if (!in || !out || !rect) return -1;

y = rect->top;
while (y < rect->bottom)
{
x = rect->left;
while ( x < rect->right)
{
int pos = (x*bytesperpixel) + (y*stride);
out[n] = ((int)in[pos] & 0xff) << 16 | ((int)in[pos+1] & 0xff) << 8 | ((int)in[pos+2] & 0xff);
n++;
x++;
}

y++;
}

return 0;
}

int median_filter_2d(unsigned char *in, unsigned char *out, int W, int H, int BytesPerPixel)
{
#define window_size 3
int temp[window_size*window_size] = { 0, };
int x = 0;
int y = 0;
int stride = W*BytesPerPixel;

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

y = 0;
while (y < H)
{
x = 0;
while (x < W)
{
RECT rect;
int pos = x*BytesPerPixel + y*stride;
int val = 0;
rect.left = x - window_size / 2;
rect.top = y - window_size / 2;
if (rect.left < 0) rect.left = 0;
if (rect.top < 0) rect.top = 0;

rect.right = rect.left + window_size;
rect.bottom = rect.top + window_size;

if (rect.right >= W) rect.right = W - 1;
if (rect.bottom >= H) rect.bottom = H - 1;
get_pixels(in, temp, &rect, stride, BytesPerPixel);
val = get_qsort_median(temp, (rect.right - rect.left)*(rect.bottom - rect.top));
out[pos] = (val & 0xff0000) >> 16;
out[pos+1] = (val & 0xff00) >> 8;
out[pos+2] = (val & 0xff);

x++;
}
y++;
}

return 0;
}

다운받은 Noise_salt_and_pepper.png파일을 위 구현한 median_fileter_2d를 사용하여 노이즈를 제거하면 아래 오른쪽 이미지를 얻을 수 있다.
왼쪽 이미지의 노이즈가 오른쪽 이미지에서는 사라진 것이 보인다.
 


[관련 포스트]

댓글

이 블로그의 인기 게시물

간단한 cfar 알고리즘에 대해

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

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

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

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