파이썬 강의/openCV

파이썬 openCV 4. 범위 강조

마리사라 2020. 11. 15. 17:50
반응형

파이썬 openCV 4번째 강의는 영상 범위 강조 입니다.

 

뭔가 다른분들의 강의글과 다르게 순서가 뒤죽박죽인것같지만 저는 이 순서대로 배워서 이 순서가 익숙하네요. 그럼 강의 시작합니다.


0. 범위 강조?

범위 강조란, 이름 그대로 일정 범위의 화소만 두드러지게 만드는 방법입니다. 이렇게 하면 명함 대조가 뚜렷해져서 해당 부분이 도드라져 보이게 됩니다.

 

범위 강조는 딱히 설명할게 없으니 바로 코드 설명 들어가겠습니다.


1. openCV에서의 범위 강조

우선 범위 강조를 하려면 범위가 필요하겠죠? 그래서 강조할 범위를 입력 받습니다.

high = int(input("최댓값 : "))
low = int(input("최솟값 : "))

 

그리고 이미지를 불러와줍니다.

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

 

openCV의 범위 강조는 흑백 사진으로 가능한데요. 그래서 원래의 컬러 이미지를 흑백으로 변환하여 줍니다(강의 1번 참조)

2020/11/14 - [파이썬/openCV] - 파이썬 openCV 1. 이진화(binarization, thresholding)

 

파이썬 openCV 1. 이진화(binarization, thresholding)

파이썬 openCV의 첫 번째 강의 이진화(binarization, thresholding)입니다. 이진화는 이름에서 알 수 있듯이, 영상(사진)을 이진법처럼 두 가지로만 분류하는 것입니다. openCV에서 이진화는 기존의 영상을

marisara.tistory.com

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

 

이제 출력할 변수에 흑백 이미지를 복사하고

out = gray.copy()

 

이제부터 범위 강조를 해야겠죠? 범위 강조의 방법은 LUT(Look Up Table)라고 하는 방법과 단순 노동의 for문으로 하는 방법이 있습니다. LUT는 나중에 다루도록하니 이번에는 단순 노동의 방법으로 해보도록 하겠습니다.

 

우선 이미지의 원리를 알아야 합니다. 이미지는 가로 * 세로 * 채널의 행렬로 이루어져 있습니다. 예를들어 BGR로 이루어진 컬러 이미지의 경우에는 가로 * 세로 * 3(B, G, R)이고, 그레이스케일(흑백)은 가로 * 세로 * 1(흑백)이겠지요.

 

그렇다면 가로와 세로의 크기는 어떻게 알 수 있을까요?

강의 0번에서 올려드렸던 lenna 이미지는 512 * 512 의 이미지입니다. 그래서 이 경우에는 512 * 512라는 것을 바로 알 수 있지만 다른 이미지로 하는 분들도 있을 수 있습니다. 그래서 가로와 세로를 알아내는 코드는

height, width, channel = img.shape

입니다. 순서대로 세로, 가로, 채널이 되겠군요. 여기서 그레이스케일이라면 channel은 필요없게됩니다.

 

 

이제 가로, 세로의 크기를 알았으니 중첩 for문을 통해 순회하도록 하겠습니다

for i in range(width):
	for j in range(height):
    		if low <= out[i][j] <= high:
        		out[i][j] = 255

중첩 for문을 자세히 살펴보면 i는 0부터 width의 크기 - 1까지 순회하고, j는 0부터 height - 1까지 순회합니다. 이때 해당 화소가 low이상 high이하일경우 해당 화소를 255로 변환합니다.

파이썬의 중첩 for문은 끔찍하게 느리지만 이정도의 연산정도는 괜찮습니다.

 

이제 화면을 출력해보겠습니다.

 

원본
128 ~ 192까지의 범위 강조

 

이렇게 범위 강조를 할 경우 경계가 뚜렷하게 보이게 됩니다.


2. 마치며

 

lenna 이미지는 범위 강조 영상으로는 좋은 이미지는 아닙니다. 여러분들이 한번 범위 강조 프로그램으로 여러 영상을 강조해보면서 범위 강조가 어떻게 쓰이는지 직접 눈으로 보는것도 좋을 것 같습니다.

 

 

import cv2

high = int(input("최댓값 : "))
low = int(input("최솟값 : "))
img = cv2.imread("lenna.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
out = gray.copy()
height, width = gray.shape
for i in range(width):
    for a in range(height):
        if low <= out[i][a] <= high:
            out[i][a] = 255
cv2.imshow("original", gray)
cv2.imshow('emphasis', out)
cv2.waitKey(0)
반응형