[[Highpass]] 필터와는 다르게 저주파 필터는 고주파는 거르고, 저주파는 통과시키는 필터이다.
일반적인 데이터에서 노이즈는 고주파에 해당되고, 우리가 원하는 데이터는 저주파에 해당되기 떄문에 저주파 필터를 통해 노이즈를 필터링할 수 있기 때문에 노이즈 제거에 사용된다.
저주파 필터를 RC 회로로 구현하면 다음과 같다.
저주파 필터의 값이 커질수록 측정값에 더 민감해지고, 작아지면 잡음 제거에 더 민감해진다
저주파 필터는 [[Gaussian Filter]]를 활용한다.
가우시안 필터의 표준편차가 클 수록 대상 점에서 멀어질수록 값이 작아지는 정도가 크기 때문에 블러링 효과는 커진다. 반대로 표준편차가 작을 수록 대상 점에서 멀어질수록 값이 작아지는 정도가 작기 때문에 블러링 효과는 작아진다.
이를 코드로 구현해보자.
void CImageDlg::LowPassFilter()
{
// 이미지가 로드되지 않았으면 반환
if (m_original == nullptr)
return;
// 결과를 저장할 임시 이미지 생성
BYTE* temp = new BYTE[IMAGE_SIZE];
memcpy(temp, m_original, IMAGE_SIZE);
// 필터 크기 설정
int pad = filterSize / 2;
// 각 픽셀에 대해
for (int y = pad; y < IMAGE_HEIGHT - pad; y++) {
for (int x = pad; x < IMAGE_WIDTH - pad; x++) {
int sum = 0;
int count = 0;
// 필터 적용
for (int i = -pad; i <= pad; i++) {
for (int j = -pad; j <= pad; j++) {
sum += m_original[(y + i) * IMAGE_WIDTH + (x + j)]; // 주변 픽셀들의 값을 다 더함
count++; // 픽셀의 수 카운트
}
}
// 평균값 계산
BYTE average = sum / count; // 주변 픽셀들의 총합을 픽셀 수로 나눠서 평균
// 결과를 임시 이미지에 저장
temp[y * IMAGE_WIDTH + x] = average;
}
}
// 결과를 m_filtered에 복사
memcpy(m_filtered, temp, IMAGE_SIZE);
delete[] temp; // 할당 해제
}
평균 필터에서는 주변 픽셀들의 값을 다 더하여 그 총합을 픽셀 수로 나누고, 그 평균을 저장한다.
이 평균 필터에 가우시안 커널을 곱하여 가중치를 적용함으로써 가우시안 필터를 구현할 수 있다.
double gaussianKernel[3][3] = {
{1.0 / 16, 2.0 / 16, 1.0 / 16},
{2.0 / 16, 4.0 / 16, 2.0 / 16},
{1.0 / 16, 2.0 / 16, 1.0 / 16}
}; // 가우시안 커널 정의. 중심에 가까운 값에 더 큰 가중치 부여
double sum = 0; // 가중치를 적용한 픽셀 값의 총합을 저장할 변수
// 필터 적용
for (int i = -1; i <= 1; i++) { // y축 방향으로 1픽셀씩 이동
for (int j = -1; j <= 1; j++) { // x축 방향으로 1픽셀씩 이동
sum += m_original[(y + i) * IMAGE_WIDTH + (x + j)] * gaussianKernel[i + 1][j + 1]; // 커널에 정의된 가중치를 적용하여 픽셀 값 더함
}
}
BYTE average = round(sum); // 가중치를 적용한 픽셀 값의 총합을 반올림하여 평균을 구함
저주파 필터는 이미지에서 낮은 주파수 성분, 즉 부드러운 부분과 대략적인 형태를 강조하는 특징이 있다. 장점으로는 노이즈를 잘 제거하고 이미지를 부드럽게 만들 수 있다는 점이 있고, 단점으로는 세밀한 부분이나 경계선을 흐리게 만들 수 있다는 점이있다.