OpenCV 필터링 기법

필터링 개요

이미지 필터링은 이미지의 품질을 개선하거나 특정 효과를 얻기 위해 사용됩니다. 주요 목적은 다음과 같습니다:

  • 노이즈 제거: 이미지의 불필요한 노이즈 제거
  • 블러 효과: 부드러운 효과, 초점 흐림 효과
  • 샤프닝: 이미지 선명도 향상
  • 전처리: 머신러닝이나 컴퓨터 비전 작업 전 이미지 품질 개선

1. 블러 필터 (Blur Filters)

블러 필터는 이미지를 부드럽게 만들어 노이즈를 제거하거나 특수 효과를 만드는 데 사용됩니다.

1.1 평균값 필터 (Average Blur)

사용 목적:

  • 간단한 노이즈 제거
  • 이미지 부드럽게 만들기
  • 빠른 처리 속도가 필요한 경우

특징:

  • 커널 내 모든 픽셀의 평균값 사용
  • 가장 간단한 블러 필터
  • 엣지 보존 능력 낮음
import cv2
import numpy as np

# 이미지 읽기
img = cv2.imread('image.jpg')

# 평균값 필터 적용
# cv2.blur(src, ksize)
# ksize: 커널 크기 (홀수, 예: (5, 5), (9, 9))
blurred = cv2.blur(img, (5, 5))

# 커널 크기가 클수록 더 강한 블러 효과
blurred_strong = cv2.blur(img, (15, 15))

파라미터:

  • ksize: 커널 크기 (width, height) - 홀수여야 함
  • 커널 크기가 클수록 블러 효과가 강해짐

1.2 가우시안 필터 (Gaussian Blur)

사용 목적:

  • 자연스러운 노이즈 제거
  • 이미지 전처리 (특히 머신러닝)
  • 가장 널리 사용되는 블러 필터
  • 엣지 검출 전 노이즈 제거

특징:

  • 가우시안 분포를 사용한 가중 평균
  • 중심 픽셀에 더 높은 가중치 부여
  • 엣지 보존 능력이 평균값 필터보다 우수
  • 자연스러운 블러 효과
# 가우시안 필터 적용
# cv2.GaussianBlur(src, ksize, sigmaX, sigmaY)
blurred = cv2.GaussianBlur(img, (5, 5), 0)

# 커널 크기와 시그마 값 조정
blurred_custom = cv2.GaussianBlur(img, (15, 15), 5.0)

# 시그마를 0으로 설정하면 자동 계산
blurred_auto = cv2.GaussianBlur(img, (5, 5), 0)

파라미터:

  • ksize: 커널 크기 (width, height) - 홀수여야 함
  • sigmaX: X 방향 가우시안 커널 표준편차 (0이면 자동 계산)
  • sigmaY: Y 방향 가우시안 커널 표준편차 (0이면 sigmaX와 동일)

사용 예시:

# 엣지 검출 전 노이즈 제거
img = cv2.imread('noisy_image.jpg', cv2.IMREAD_GRAYSCALE)
blurred = cv2.GaussianBlur(img, (5, 5), 0)
edges = cv2.Canny(blurred, 100, 200)

1.3 양방향 필터 (Bilateral Filter)

사용 목적:

  • 엣지를 보존하면서 노이즈 제거
  • 이미지 부드럽게 만들되 선명도 유지
  • 포토샵 스타일의 자연스러운 블러 효과

특징:

  • 공간적 거리와 색상 차이를 모두 고려
  • 엣지 보존 능력이 매우 우수
  • 처리 속도가 상대적으로 느림
  • 자연스러운 스킨 톤 보정에 유용
# 양방향 필터 적용
# cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace)
filtered = cv2.bilateralFilter(img, 9, 75, 75)

# 파라미터 조정
filtered_strong = cv2.bilateralFilter(img, 15, 100, 100)

파라미터:

  • d: 필터링에 사용되는 픽셀 이웃의 직경 (권장: 5, 9, 15)
  • sigmaColor: 색상 공간의 표준편차 (값이 클수록 더 많은 색상이 함께 필터링됨)
  • sigmaSpace: 좌표 공간의 표준편차 (값이 클수록 더 먼 픽셀들이 영향을 미침)

사용 예시:

# 엣지를 보존하면서 노이즈 제거
noisy_img = cv2.imread('noisy_image.jpg')
smoothed = cv2.bilateralFilter(noisy_img, 9, 75, 75)

# 포트레이트 이미지 스킨 톤 보정
portrait = cv2.imread('portrait.jpg')
soft_skin = cv2.bilateralFilter(portrait, 9, 50, 50)

2. 샤프닝 필터 (Sharpening Filters)

샤프닝 필터는 이미지의 선명도를 향상시키는 데 사용됩니다.

2.1 흑백 이미지 샤프닝

사용 목적:

  • 흐릿한 이미지 선명도 향상
  • 텍스트 인식 전처리
  • 엣지 강조
import cv2
import numpy as np

# 그레이스케일 이미지 읽기
img = cv2.imread('blurry_image.jpg', cv2.IMREAD_GRAYSCALE)

# 방법 1: 라플라시안 필터 사용
laplacian = cv2.Laplacian(img, cv2.CV_64F)
sharpened = np.uint8(np.clip(img - 0.5 * laplacian, 0, 255))

# 방법 2: 커널을 사용한 샤프닝
kernel = np.array([[-1, -1, -1],
                   [-1,  9, -1],
                   [-1, -1, -1]])
sharpened = cv2.filter2D(img, -1, kernel)

# 방법 3: 언샤프 마스킹 (Unsharp Masking) - 권장
# 원리: 블러된 이미지를 원본에서 빼서 엣지 정보(마스크)를 추출한 후, 이를 원본에 더함
blurred = cv2.GaussianBlur(img, (5, 5), 0)
mask = cv2.subtract(img, blurred)

# 가중치를 조절하여 샤프닝 강도 제어
# cv2.addWeighted(src1, alpha, src2, beta, gamma)
# alpha: 원본 이미지 가중치, beta: 마스크 가중치
sharpened = cv2.addWeighted(img, 1.5, mask, 0.5, 0)

# 샤프닝 강도 조절 예시
# 약한 샤프닝: cv2.addWeighted(img, 1.2, mask, 0.2, 0)
# 강한 샤프닝: cv2.addWeighted(img, 2.0, mask, 1.0, 0)

2.2 컬러 이미지 샤프닝

사용 목적:

  • 컬러 이미지 선명도 향상
  • 사진 후처리
  • 디지털 아트 효과
# 컬러 이미지 읽기
img = cv2.imread('blurry_image.jpg')

# 방법 1: 각 채널별로 샤프닝
b, g, r = cv2.split(img)

# 각 채널에 샤프닝 커널 적용
kernel = np.array([[-1, -1, -1],
                   [-1,  9, -1],
                   [-1, -1, -1]], dtype=np.float32)

b_sharp = cv2.filter2D(b, -1, kernel)
g_sharp = cv2.filter2D(g, -1, kernel)
r_sharp = cv2.filter2D(r, -1, kernel)

# 채널 합치기
sharpened = cv2.merge([b_sharp, g_sharp, r_sharp])

# 방법 2: YUV 색공간에서 Y 채널만 샤프닝 (더 자연스러움)
img_yuv = cv2.cvtColor(img, cv2.COLOR_BGR2YUV)
y, u, v = cv2.split(img_yuv)

# Y 채널만 샤프닝
y_sharp = cv2.filter2D(y, -1, kernel)

# 채널 합치기
img_yuv_sharp = cv2.merge([y_sharp, u, v])
sharpened = cv2.cvtColor(img_yuv_sharp, cv2.COLOR_YUV2BGR)

# 방법 3: 언샤프 마스킹 (컬러)
blurred = cv2.GaussianBlur(img, (5, 5), 0)
sharpened = cv2.addWeighted(img, 1.5, cv2.subtract(img, blurred), -0.5, 0)

커널 종류:

# 강한 샤프닝 커널
kernel_strong = np.array([[-1, -1, -1],
                          [-1,  9, -1],
                          [-1, -1, -1]])

# 중간 샤프닝 커널
kernel_medium = np.array([[ 0, -1,  0],
                         [-1,  5, -1],
                         [ 0, -1,  0]])

# 약한 샤프닝 커널
kernel_weak = np.array([[ 0, -0.5,  0],
                       [-0.5,  3, -0.5],
                       [ 0, -0.5,  0]])

3. 노이즈 제거 필터 (Noise Reduction Filters)

3.1 메디안 필터 (Median Filter)

사용 목적:

  • 솔트 앤 페퍼 노이즈 제거 (점 노이즈)
  • 임펄스 노이즈 제거
  • 엣지 보존하면서 노이즈 제거

특징:

  • 커널 내 픽셀 값의 중앙값 사용
  • 이상치(outlier)에 강함
  • 엣지 보존 능력 우수
  • 가우시안 노이즈에는 효과적이지 않음
# 메디안 필터 적용
# cv2.medianBlur(src, ksize)
# ksize: 커널 크기 (홀수, 1, 3, 5, 7, 9 등)
filtered = cv2.medianBlur(img, 5)

# 강한 노이즈 제거
filtered_strong = cv2.medianBlur(img, 9)

파라미터:

  • ksize: 커널 크기 (홀수, 1보다 큰 값)
  • 커널 크기가 클수록 더 강한 노이즈 제거 (처리 시간 증가)

사용 예시:

# 솔트 앤 페퍼 노이즈가 있는 이미지
noisy_img = cv2.imread('noisy_image.jpg')
cleaned = cv2.medianBlur(noisy_img, 5)

# 그레이스케일 이미지
gray = cv2.imread('noisy_image.jpg', cv2.IMREAD_GRAYSCALE)
cleaned_gray = cv2.medianBlur(gray, 5)

필터 선택 가이드

노이즈 제거

  • 솔트 앤 페퍼 노이즈: 메디안 필터
  • 가우시안 노이즈: 가우시안 블러 또는 비국소 평균 필터
  • 일반 노이즈: 가우시안 블러 (빠름) 또는 양방향 필터 (엣지 보존)

블러 효과

  • 빠른 처리: 평균값 필터
  • 자연스러운 효과: 가우시안 블러
  • 엣지 보존: 양방향 필터

선명도 향상

  • 흑백 이미지: 라플라시안 또는 커널 기반 샤프닝
  • 컬러 이미지: YUV 색공간에서 Y 채널만 샤프닝 (권장)