본문 바로가기
Python/Computer Vision

[파이썬, Python] OpenCV - 영상의 필터링, 블러링, 엣지(Edge)검출

by coding-choonsik 2023. 9. 1.
728x90
반응형
SMALL

1. 필터링(filtering)

  • 커널(filter)이라고 하는 행렬을 정의하고, 이 커널을 이밎 위에서 이동시켜 가면서  커널과 겹쳐진 이미지 영역과 연산을 한 후, 그 결과값을 연산을 진행한 이미지 픽셀을 대신하여  새로운 이미지를 만드는 연산
  • cv2.filter2D(영상, 이미지 깊이, 커널, 중심점 좌표, 추가될 값, 가장자리 화소 처리)
    • 이미지 깊이: -1(입력과 동일)
    • 커널행렬: 3*3, 5*5, ... 가로 세로가 동일한 행렬 사용
    • 중심점 좌표: 기본값은 왼쪽 상단
    • 추가될 값: 행렬연산 후 더해지는 값
    • 가장자리 화소 처리
      • BORDER_CONSTANT: 000abcdefg000, 가장 자리를 0으로 채움(검정색)
      • BORDER_REPLICATE: aaaabcedfgggg, 가장 자리를 가장 끝 픽셀로 채움
                ...

 

 

2. 블러링(Blurring)

  • 초점이 맞지 않은듯 영상을 흐릿하게 하는 작업
  • 평균 블러링
    • 가장 일반적인 블러링 방법으로 균일한 값으로 정규화된 커널을 이용한 이미지 필터링 방법
    • 커널 영역 내에서 평균 값으로 해당 픽셀을 대체함
    • 주변 픽셀들의 평균값을 적용하면 픽셀 간 차이가 적어져 선명도가 떨어져 전체적으로 흐려짐
    • 필터의 크기가 클수록 평균 블러링을 적용했을 때 선명도가 떨어짐
    • cv2.blur(영상, 커널사이즈)

 

import cv2
import matplotlib.pyplot as plt
import numpy as np

img = cv2.imread('dog.bmp')
dst1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # matplotlib으로 띄우기 위해
dst2 = cv2.blur(img, (3, 3))
plt.figure(figsize=(10,5))
cv2.imshow('img', img)
cv2.imshow('dst2', dst2)

# filter2D를 이용하여 블러링
for i, k in enumerate([3, 5, 9]):  # 커널사이즈
    kernel = np.ones((k, k)) / k ** 2
    # -1: 입력과 동일한 크기
    filtering = cv2.filter2D(dst1, -1, kernel)
    plt.subplot(1,3,i+1)
    plt.imshow(filtering)
    plt.title('kernel size:{}'.format(k))
    plt.axis('off')
plt.show()


cv2.waitKey()


  • 가우시안 블러링
    • 가우시안 분포를 갖는 커널로 블러링 하는 것(정규 분포, 평균 근처에 몰려 있는 값들의 개수가 많고 평균에서 멀어질수록 그 개수가 적어지는 분포)
    • 대상 픽셀에 가까울수록 많은 영향을 주고, 멀어질수록 적은 영향을 주기 때문에 원래의 영상과 비슷하면서도 노이즈를 제거하는 효과가 있음
    • cv2.GaussianBlur(영상, 출력영상, 커널사이즈)
      • 출력영상: (0,0)이면 입력 영상과 같음
      • 커널사이즈: 숫자 1개만 적음 예) 3 -> 3*3 커널
import cv2

img = cv2.imread('dog.bmp', cv2.IMREAD_GRAYSCALE)
dst1 = cv2.GaussianBlur(img, (0, 0), 3)
dst2 = cv2.blur(img, (3, 3))

cv2.imshow('img', img)
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()

▲ 순서대로 img, dst1, dst2


  • 미디언 블러링
    • 커널의 픽셀 값 중 중앙값을 선택
    • 소금-후추 잡음을 제거하는 효과
    •  cv2.medianBlur(영상, 커널)
import cv2

img = cv2.imread('noise.bmp', cv2.IMREAD_GRAYSCALE)
dst = cv2.medianBlur(img, 3)

cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()

▲ img와 dst


  • 바이레터럴 필터(Bilateral Filter)
    • 기존 블러링의 문제점(잡음을 제거하는 효과는 뛰어났지만, 경계도 흐릿하게 만드는 문제)을 개선하기 위해 나온 필터링 기법
    • 경계도 뚜렷하고 노이즈도 제거되는 효과가 있지만, 속도가 느리다는 단점
    • cv2.bilateralFilter(영상, 픽셀의 거리, 시그마컬러, 시그마스페이스)
    • 픽셀의 거리(필터의 직경): -1을 입력하면 자동 결정됨, 5보다 크면 매우 느림
      • sigmaColor: 색공간의 시그마 값
      • sigmaSpace: 좌표공간의 시그마 값, 값이 크면 멀리 떨어져 있는 픽셀들이 서로 영향을 미침

import cv2

img = cv2.imread('gaussian_noise.jpg', cv2.IMREAD_GRAYSCALE)
dst = cv2.bilateralFilter(img, 9, 75, 75)
dst2 = cv2.bilateralFilter(img, 5, 80, 80)

cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.imshow('dst2', dst2)
cv2.waitKey()

▲ 순서대로 img, dst, dst2

 


3. 에지(Edge) 검출

  • 영상에서 화소의 밝기가 급격하게 변하는 부분
  • 물체의 윤곽선(경계선)이 해당
  • 에지를 검출할 수 있으면 물체의 윤곽선을 알 수 있음
  • '케니 에지 검출'은 상당한 수준으로 에지를 신뢰성 있게 검출하는 방법
    1. 노이즈 제거: 5*5 가우시안 블러링 필터
    2. 경계 그레디언트 방향 계산: 소벨 필터로 경계 및 그레디언트 방향 검출
    3. 비최대치 억제: 그레디언트 방향에서 검출된 경계 중 가장 큰 값만 선택하고 나머지는 제거
    4. 이력 스레시홀딩: 두 개의 경계값(Max, Min)을 지정해서 경계 영역에 있는 픽셀들 중 큰 경계값(Max) 밖의 픽셀과 연결성이 없는 픽셀을 제거
  • cv2.Canny(영상, 최소임계값, 최대임계값, 커널)
import cv2
import numpy as np

img = cv2.imread('dog.bmp')
med_eval = np.median(img)
lower = int(max(0, 0.7*med_eval))  # 중앙값의 70%의 값이 0보다 작아질 경우 0으로 설정
upper = int(min(255, 1.3*med_eval))  # 중앙값의 130%값이 255를 넘어가면 255로 설정

dst = cv2.GaussianBlur(img, (3, 3,), 0, 0)
dst = cv2.Canny(dst, lower, upper, 3)

cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()

▲ img와 dst

 

728x90
반응형
LIST