파이썬 강의/openCV

파이썬 openCV 6. end-in 기법

마리사라 2020. 11. 18. 11:28
반응형

파이썬 openCV 6번째 강의는 전 강의에서 이어지는 스트레칭의 기법 중 하나인 end-in 기법입니다. 스트레칭에 대한 정보를 더 보고 싶으시면 이전 강의를 참조해주세요!

2020/11/16 - [파이썬/openCV] - 파이썬 openCV 5. 명암대비 스트레칭(streching)

 

파이썬 openCV 5. 명암대비 스트레칭(streching)

파이썬 openCV 5번째 강의는 명암대비 스트레칭입니다. 여러분들도 근육이 뭉쳤을때 스트레칭을 통해 근육을 풀어주곤 하죠? 이미지도 마찬가지로 스트레칭이 가능한데요. 이번 시간에 스트레칭

marisara.tistory.com


0. end-in 기법?

end-in 기법은 스트레칭 기법을 적용하면서, 조건을 달아주는 것입니다. 조건은 양 끝 값의 일정 부분을 잘라내는 것! 그렇게 함으로써 이미지의 명암 대비가 더 뚜렷하게 보이게 하는 방법입니다.

 

그래서 스트레칭 기법과 크게 다르지 않지만 몇 가지 작업이 추가된 형식이죠.


1. openCV에서의 end-in 기법

end-in기법의 코드는 앞서 말씀드렸다시피 스트레칭의 코드와 크게 다르지 않습니다. 하지만 앞의 강의는 관심 없고 이번 강의만 관심이 있는 분들도 계실 수 있으니 처음부터 차근차근 알려드리겠습니다. ^^

 

import cv2
import matplotlib.pyplot as plt

opencv를 사용하기 위한 모듈과, 히스토그램을 보기 위한 모듈을 import 해줍니다

 

img = cv2.imread("lenna.png")

이미지를 불러와줍니다.

 

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

명암대비 스트레칭 기법이니 그레이 스케일(흑백)로 변환해줍니다.

 

height, width = gray.shape

이미지 크기만큼 연산해야 하니 세로, 가로의 크기를 미리 저장해줍니다.

 

MIN = gray.min()
MAX = gray.max()

이번에도 이미지의 최솟값과 최댓값을 계산해줍니다.

 

low = int(input("하한값 : "))
high = int(input("상한값 : "))

이 부분이 기존 명암대비 스트레칭과 다른 부분입니다. 기존 명암대비 스트레칭은 모든 화소에 대해서 스트레칭 공식을 적용했습니다. 그러나 end-in기법은 하한 값과 상한 값을 정해두고 하한값 미만의 값들은 0, 상한값 초과의 값들은 255로 변환하고 이후 나머지의 값들은 스트레칭 공식을 적용합니다.

 

하한 값과 상한값을 정하는 방법은 여러가지가 있지만, 기본적으로는 히스토그램의 일정 퍼센트만큼 남기는 방법을 사용합니다. 원래 화소의 80퍼센트만 남긴다면, 좌우로 10퍼센트씩 하한값과 상한 값으로 만들고, 나머지만 스트레칭 공식을 적용하는 거죠. 우선 이번 시간은 유연하게 적용할 수 있게 직접 입력받도록 했습니다.

 

for i in range(width):
	for j in range(height):
            if gray[i][j] < low:
                out[i][j] = 0
            if gray[i][j] > high:
            	out[i][j] = 255
            else:
            	out[i][j] = ((gray[i][j] - MIN) * 255) / (MAX - MIN)

이제 중첩 for문을 사용하여 low미만의 값은 0, high초과의 값은 255, 나머지는 스트레칭 공식을 적용해줍니다.

 

cv2.imshow("original", gray)
cv2.imshow("end_in", out)

이제 결과 이미지를 출력해줍니다

 

히스토그램도 봐야겠죠?

plt.figure()

히스토그램 출력을 위한 공간을 만들어줍니다.

 

plt.subplot(1, 2, 1)

출력 공간에 (1, 2) 크기의 하위 공간을 만들고, 그 첫 번째 칸에 접근합니다

 

plt.hist(gray.ravel(), 256, [0, 256])

해당 칸에 gray의 히스토그램을 출력합니다

 

plt.subplot(1, 2, 2)
plt.hist(out.ravel(), 256, [0, 256])

같은 방법으로 두 번째 칸에 out의 히스토그램을 출력합니다

 

plt.show()

마지막으로 히스토그램까지 화면에 출력하면 끝이 납니다.

 

 

 

원본영상
end-in기법 적용 영상(30, 220)
좌 : 원본영상 / 우 : end-in기법 적용 영상

 

크게 차이는 않나지만 이미지에서 명암대비가 어느 정도 뚜렷해진 걸 알 수 있습니다. 히스토그램을 보면 end-in기법을 적용한 영상의 히스토그램은 왼쪽과 오른쪽의 일부분이 잘려있는 것을 볼 수 있습니다. end-in기법이 잘 적용됐네요.


2. 마치며

기존 명암대비 스트레칭 기법보다 end-in기법이 명암의 대비는 더 뚜렷하게 나타낼 수 있고, 이미지의 용량도 어느 정도 줄어드는 효과가 있습니다. 사용하시는 영상과 상황에 따라 기존 명암대비 스트레칭을 사용하실지 end-in기법을 사용하실지 선택하시면 될 것 같습니다.

 

 

import cv2
import matplotlib.pyplot as plt


img = cv2.imread('lenna.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
height, width = gray.shape
MIN = gray.min()
MAX = gray.max()
out = gray.copy()
low = int(input("하한값 : "))
high = int(input("상한값 : "))
for i in range(width):
    for j in range(height):
        if gray[i][j] < low:
            out[i][j] = 0
        elif gray[i][j] > high:
            out[i][j] = 255
        else:
            out[i][j] = ((gray[i][j] - MIN) * 255) / (MAX - MIN)
cv2.imshow('original', gray)
cv2.imshow('end_in', out)

plt.figure()
plt.subplot(1, 2, 1)
plt.hist(gray.ravel(), 256, [0, 256])
plt.subplot(1, 2, 2)
plt.hist(out.ravel(), 256, [0, 256])
plt.show()

cv2.waitKey()
반응형