OpenCV-Python

OpenCV Python 필터링 - 날카로운 영상 만들기: 언샤프(unsharp) 필터

rkftks22 2021. 8. 23. 13:34

날카롭지 않은 영상(unsharp), 부드러워진 영상을 이용하여 날카로운 영상을 생성하는 필터입니다.

 

언샤프 마스크 필터링의 연산과정입니다.

기존 픽셀
가우시안 필터 적용된 픽셀
기존 픽셀 - 가우시안 필터 적용된 픽셀
언샤프 마스크 필터

 


흑백 영상

import cv2
import numpy as np

img = cv2.imread("imgs/Lenna.png", cv2.IMREAD_GRAYSCALE)

filter_img = cv2.GaussianBlur(img, (0, 0), 2)

dst = cv2.addWeighted(img, 2, filter_img, -1, 0)
#dst = np.clip(2.0*img - filter_img, 0, 255).astype(np.uint8)

cv2.imshow("Lenna", img)
cv2.imshow("dst", dst)


cv2.waitKey()
cv2.destroyAllWindows()

 

Gaussianblur값을 2로 했을 때 변화
Gaussianblur값을 5로 했을 때 변화

 

가우시안 필터의 값을 바꿔주면 효과가 더 두드러지네요.

 

dst3 = cv2.addWeighted(img, 2, filter_img, -1, 0)
#dst3 = np.clip(2.0*img2 - filter_img, 0, 255).astype(np.uint8)
# 두 식은 동일합니다.

 

cv2.addWeighted(src1, alpha, src2, beta, gamma [, dst [, dtype]])  [] : 생략 가능

src1 : 입력 영상 1

alpha : 입력 영상 1에 대한 가중치

src2 : 입력 영상 2

beta : 입력 영상 2에 대한 가중치

gamma : 추가로 더해줄 값

 

np.clip : 이미지는 그냥 출력해보면 숫자들로 이루어진 배열인데

           np.clip(2.0*img2 - filter_img, 0, 255) 2.0 * img2 - filter_img 배열을 계산 한 값을

           np.clip(2.0*img2 - filter_img, 0, 255) 0 ~ 255 사이의 값으로 정해준다는 의미입니다. 

 

astype(np.uint8)은 np.clip(2.0*~) 과정에서 float 형태로 결과가 출력되기 때문에 int형으로 바꿔준 것입니다.

 


컬러 영상

import cv2
import numpy as np

img = cv2.imread("imgs/Lenna.png") 

img_ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)

img_f = img_ycrcb[:, :, 0].astype(np.float32)

img_blr = cv2.GaussianBlur(img_f, (0, 0), 2.0)

img_ycrcb[:, :, 0] = np.clip(2.0*img_f - img_blr, 0, 255).astype(np.uint8)

dst = cv2.cvtColor(img_ycrcb, cv2.COLOR_YCrCb2BGR)

cv2.imshow("Lenna", img)
cv2.imshow("dst", dst)
cv2.waitKey()
cv2.destroyAllWindows()

날카롭지 않은 영상(unsharp), 부드러워진 영상을 이용하여 날카로운 영상을 생성하는 필터입니다.

출력 결과

 

img2_ycrcb = cv2.cvtColor(img2, cv2.COLOR_BGR2YCrCb)

 

YCrCb로 변경하는 이유는 YCrCb는 Y, Cr, Cb 채널로 이루어져 있습니다. 이때 Y는 밝기, Cr, Cb는 색상 정보입니다. 

 

img2_f = img2_ycrcb[:, :, 0].astype(np.float32)
img2_blr = cv2.GaussianBlur(img2_f, (0, 0), 2.0)
img2_ycrcb[:, :, 0] = np.clip(2.0*img2_f - img2_blr, 0, 255).astype(np.uint8)
dst = cv2.cvtColor(img2_ycrcb, cv2.COLOR_YCrCb2BGR)

 

[ : , : , 0] : x(0~끝), y(0~끝), 밝기 부분(0 채널)만 추출해내면 Gray부분이 나옵니다.

float32 실수형 변환은 가우시안 필터링을 할 때 출력 영상타입이 입력 영상과 같은 타입으로 정수형 그대로 진행할

경우 소수점 밑의 자리가 다 날라가기 때문에 미세한 변화가 사라질 수 있습니다.

 

밝기 영상만 끄집어내어 흑백 영상에 대하여 필터링을 거쳤던 작업과 똑같은 작업을 진행한 다음

다시 컬러 영상으로 바꾸는 작업을 진행하게 되면 컬러 영상의 언샤프 필터링이 이루어집니다. 

밝기 부분만 끄집어내어 최대한 색상 정보가 변하게 되는 것을 막아주기 위한 작업인 것 같습니다.