[OpenCV] 이미지 필터링

20166 단어 pythonTILopencvTIL

Convolution Kernel

이미지 처리에서 컨볼루션 커널은 이미지를 필터링하는 데 사용되는 2D 행렬이다. 컨볼루션 행렬이라고도 하는 컨볼루션 커널은 일반적으로 정사각형 MxN 행렬이다. 여기서 M과 N 은 모두 홀수인 정수다(예: 3x3, 5x5, 7x7 등)

위의 그림은 3 x 3 행렬이다.

컨볼루션 커널을 사용하여 이미지의 각 픽셀에 대해 수학적 연산을 수행하여 원하는 효과(이미지를 흐리게 하거나 선명하게 하는 것과 같은)를 얻을 수 있다.

커널을 사용해서 이미지 필터링

소스 이미지의 필터링은 이미지와 커널을 컨벌루션하여 수행된다. 간단히 말해서 커널과 이미지의 컨볼루션은 커널과 이미지의 해당 요소 간의 간단한 수학 연산이다.

  1. 커널의 중심이 이미지의 특정 픽셀(p) 위에 있다고 가정한다.
  2. 그런 다음 커널의 각 요소 값(이 경우 1)을 소스 이미지의 해당 픽셀 요소(픽셀 강도)와 곱한다.
  3. 이제 이러한 곱셈의 결과를 더하고 평균을 계산한다.
  4. 마지막으로 픽셀(p)의 값을 방금 계산한 평균 값으로 바꾼다.

이미지에 ID 커널 적용

Identity Kernel은 아래와 같이 중간 요소가 1이고 다른 모든 요소가 0인 정사각형 행렬이다.

순서

  1. 테스트 이미지 읽기
  2. 3×3 NumPy 배열을 사용하여 ID 커널을 정의
  3. filter2D() OpenCV 의 함수를 사용 하여 선형 필터링 작업 수행
  4. imshow()를 사용해서 원본 및 필터링된 이미지 표시
  5. imwrite()를 사용하여 필터링된 이미지를 디스크에 저장

filter2D()

filter2D(src, depth, kernel)
  • src : 원본 이미지
  • depth : 결과 이미지의 깊이를 나타낸다. -1이면 최종 이미지의 깊이가 원본 이미지와 동일
  • kernel : 소스 이미지에 적용하는 커널

코드

import cv2
import numpy as np

# 테스트 이미지 읽기
image = cv2.imread('test.jpg')

# ID 커널 정의
kernel1 = np.array([[0, 0, 0],
                    [0, 1, 0],
                    [0, 0, 0]])

# filter2D를 사용해서 이미지에 커널 적용
identity = cv2.filter2D(src=image, ddepth=-1, kernel=kernel1)

# 이미지 표시
cv2.imshow('Original', image)
cv2.imshow('Identity', identity)

cv2.waitKey()
cv2.imwrite('identity.jpg', identity)
cv2.destroyAllWindows()

결과

2D 컨볼루션 커널로 이미지 흐리게 처리

사용자 정의 커널을 정의하고 OpenCV의 filter2D() 기능을 사용하여 소스 이미지에 필터링 작업을 적용한다.

1개로만 구성된 5×5 커널을 정의하는 것으로 시작한다. 커널을 25로 나누기도 합니다. 그 이유는 이미지에 컨볼루션을 적용하기 전에 2D 컨볼루션 행렬을 사용하여 모든 값이 정규화되었는지 확인하기 위해서다. 커널의 각 요소를 커널의 요소 수(이 경우 25)로 나누어 수행됩니다. 이렇게 하면 모든 값이 [0, 1] 범위 내에 유지됩니다.

코드

# blur kernel 적용
kernel2 = np.ones((5, 5), np.float32) / 25
img = cv2.filter2D(src=image, ddepth=-1, kernel=kernel2)

# 이미지 표시
cv2.imshow('Original', image)
cv2.imshow('Kernel Blur', img)

cv2.waitKey()
cv2.imwrite('blur_kernel.jpg', img)
cv2.destroyAllWindows()

결과

OpenCV 내장 함수로 이미지 흐리게 처리

OpenCV의 내장 blur() 기능을 사용하여 이미지를 흐리게 할 수도 있다. 본질적으로 편의 기능은 커널을 특별히 정의할 필요가 없는 이미지를 흐리게 하는 데 사용합니다. 아래 코드와 같이 입력 인수 ksize를 사용하여 커널 크기를 지정하기만 하면 됩니다. 그런 다음 흐림 기능은 내부적으로 5×5 흐림 커널을 만들고 소스 이미지에 적용합니다.

함수 를 사용하는 아래 예제는 blur() 함수를 사용한 위 예제와 정확히 동일한 출력을 생성합니다 filter2d()

코드

# blur 함수 사용해서 이미지 블러 처리
img_blur = cv2.blur(src=image, ksize=(5,5))

# Display using cv2.imshow()
cv2.imshow('Original', image)
cv2.imshow('Blurred', img_blur)

cv2.waitKey()
cv2.imwrite('blur.jpg', img_blur)
cv2.destroyAllWindows()

결과

이미지에 GaussianBlur 적용하기

가우시안 필터는 균일 평균과 반대로 가중 평균을 수행한다. 이 경우 가우스 흐림 효과는 커널 중심으로부터의 거리에 따라 픽셀 값에 가중치를 부여한다. 중심에서 멀리 떨어진 픽셀은 가중 평균에 미치는 영향이 적다. GaussianBlur()는 이미지를 합성한다.

GaussianBlur()

GaussianBlur(src, ksize, sigmaX, dst, sigmaY, borderType)
  • src : 필터링할 원본 이미지
  • ksize : 가우스 커널의 크기를 정의
  • sigmaX : x방향 sigma
  • dst : 출력 영상. src와 같은 크기, 같은 타입
  • sigmaY : y방향 sigma. 0이면 sigmaX와 같게 설정
  • borderType : 가장자리 픽셀 확장 방식

코드

# Gaussian blur 적용
gaussian_blur = cv2.GaussianBlur(src=image, ksize=(5,5), sigmaX=0, sigmaY=0)

# 이미지 표시
cv2.imshow('Original', image)
cv2.imshow('Gaussian Blurred', gaussian_blur)
    
cv2.waitKey()
cv2.imwrite('gaussian_blur.jpg', gaussian_blur)
cv2.destroyAllWindows()

결과

이미지에 중앙 흐림값 적용

OpenCV의 medianBlur() 기능을 사용하여 중앙값 흐림 효과를 적용할 수도 있다 . 중앙값 흐림 효과에서 소스 이미지의 각 픽셀은 커널 영역에 있는 이미지 픽셀의 중앙값으로 대체된다.

medianBlur()

medianBlur(src, ksize)
  • src : 원본 이미지
  • ksize : 커널 크기. 양의 홀수인 정수

코드

# Median blur 적용
median = cv2.medianBlur(src=image, ksize=5)

# 이미지 표시
cv2.imshow('Original', image)
cv2.imshow('Median Blurred', median)
    
cv2.waitKey()
cv2.imwrite('median_blur.jpg', median)
cv2.destroyAllWindows()

결과

2D 컨볼루션 커널로 이미지 선명하게 처리

아래 코드는 sharpening kernel을 정의해서 이미지를 선명하게 했다. 이 외에도 일반적으로 사용되는 커널을 사용해볼 수 있다.

코드

샤프닝 커널 정의
kernel3 = np.array([[0, -1,  0],
                   [-1,  5, -1],
                    [0, -1,  0]])
sharp_img = cv2.filter2D(src=image, ddepth=-1, kernel=kernel3)

# 이미지 표시
cv2.imshow('Original', image)
cv2.imshow('Sharpened', sharp_img)
    
cv2.waitKey()
cv2.imwrite('sharp_image.jpg', sharp_img)
cv2.destroyAllWindows()

결과

이미지에 양방향 필터 적용

흐림 효과는 이미지의 노이즈를 줄이는 효과적인 방법일 수 있지만 중요한 세부 정보와 날카로운 가장자리가 손실될 수 있으므로 전체 이미지를 흐리게 하는 것은 바람직하지 않은 경우가 많다. 이러한 경우 bilateral filtering 을 사용하면 좋다.

이 기술은 필터를 선택적으로 적용하여 이웃의 유사한 강도 픽셀을 흐리게 한다. 가능한 한 날카로운 모서리가 유지된다. 이를 통해 필터의 공간 크기뿐만 아니라 필터링된 출력에 인접 픽셀이 포함되는 정도도 제어할 수 있다. 이는 색상 강도의 변화와 필터링된 픽셀과의 거리에 따라 수행된다.

양방향 필터링은 기본적으로 2D 가우시안(가중치) 흐림 효과를 이미지에 적용하는 동시에 인접 픽셀의 강도 변화를 고려하여 가장자리 근처의 흐림 현상을 최소화 한다(보존하고자 함). 이것이 의미하는 바는 커널의 모양이 실제로 모든 픽셀 위치에서 로컬 이미지 콘텐츠에 의존한다는 것이다.

bilateralFilter()

bilateralFilter(src, d, sigmaColor, sigmaSpace)
  • src : 원본 이미지
  • d : 필터링에 사용되는 이웃 픽셀의 지름
  • sigmaColor : 컬러공간의 시그마공간 정의, 클수록 이웃한 픽셀과 기준 색상의 영향이 커진다
  • sigmaSapce : 시그마 필터를 조정. 값이 클수록 긴밀하게 주변 픽셀에 영향을 미친다. d>0 이면 영향을 받지 않고, 그 외에는 d 값에 비례.

코드

# Bilateral 필터링 적용
bilateral_filter = cv2.bilateralFilter(src=image, d=9, sigmaColor=75, sigmaSpace=75)

# 이미지 표시
cv2.imshow('Original', image)
cv2.imshow('Bilateral Filtering', bilateral_filter)

cv2.waitKey(0)
cv2.imwrite('bilateral_filtering.jpg', bilateral_filter)
cv2.destroyAllWindows()

결과


좋은 웹페이지 즐겨찾기