본문 바로가기
소개 및 일상?

OPENCV 정리1 - 중요하다고 여기는 것

by juhongyee 2023. 8. 5.

서론

Opencv에 대해서 배웠습니다. 인공지능을 하다보면 아무래도 많이 사용하게 될텐데 확실히 기억하고자 글을 적어요.

1번은 제가 중요하다고 생각하는 것

2번은 나중에 Opencv를 많이 써보고 가장 많이 사용하게 되는 것을 적어볼 예정입니다.

 

1장도 오래오래 거쳐서 써야할듯 해요.

그러면 이제 시작해봅시다.

 

본론

1. 대비

대비는 밝기와 관련

대비(Contrast)는 밝기와 관련이 있습니다.

 

"대비 = (밝기의 최대값 - 밝기의 최소값) / (밝기의 최대값 + 밝기의 최소값)"

 

일반적으로, 흑백 이미지에서 픽셀의 밝기는 0(검정) ~ 255(흰색)으로 나타납니다.

컬러이미지에서는 픽셀의 R,G,B(or B,G,R) 의 값을 평균 내면 그 픽셀의 밝기를 알 수 있습니다.

 

이 때 대비는 어두운 부분과 밝은 부분 간의 차이를 나타내는 측정값입니다.

 

1) 공식의 핵심은 분자입니다. 이미지에서 가장 밝은 부분과, 가장 어두운 부분의 차이의 값을 안다면 그 이미지에서 밝기의 차이는 가장 잘 쳐줘봤자 분자의 값입니다.

그것이 즉, 이미지에서 어두움과 밝기의 차이가 됩니다.

 

2) 분모는 1과 -1 사이로 값이 존재하도록 정규화해주는 역할을 합니다.

 

생각

1 밝은 이미지에서 대비가 작다면 대체적으로 밝은 픽셀들이고 서로의 밝기 차이가 크지 않겠죠.

2 같은 색도 인접한 색의 밝기에 따라 다르게 보입니다.

3 인간은 대비에 민감하다.

2. 코드

- cv2.waitKey

cv2.waitKey([,delay])

설명 : delay(ms단위) 시간만큼 키 입력을 대기하고, 키 이벤트가 발생하면 해당 키 값 반환합니다.

 

delay가 0이라면 키 이벤트 발생까지 무한대기합니다. ( ex. cv2,waitKey(0))

 

-cv2.destroyALLwindows()

모든 window들을 닫아주는 코드 - 아래에 꼭 넣어줄 것.

만약 작동 안하면! ctrl+c로 Interrupt를 넣어주거나 인터프리터를 강제 종료해버리면 된다(어떻게 알게 됐을까...?)

 

- 코드

import cv2
import numpy as np

switch_case = {
    ord('a'): "a",                      # ord() 함수- 문자를 아스키코드로 변환​

    ord('b'): "b",
    ord('c'): "c",
    ord('d'): "d",
  0x41: "A키 입력",
  int('0x42', 16): "B키 입력",             

  2424832: "왼쪽 화살표",                # 0x250000​

  2490368: "윗쪽 화살표",                # 0x260000​

  2555904: "오른쪽 화살표",               # 0x270000​

  2621440: "아래쪽 화살표"                # 0x280000​

}

image = np.ones((200, 300), np.float64)         # 화소값이 1인 행렬 생성​

cv2.namedWindow('Keyboard Event')           # 윈도우 이름​

cv2.imshow('Keyboard Event', image)

while True:                                 # 무한 반복​

    key = cv2.waitKeyEx(0)                # 100ms 동안 키 이벤트 대기​

    try:
        result = switch_case[key]
        print(result)
    except KeyError:

        result = -1
    
    if key == 27: break                     # ESC 키 누르면 종료​
    
cv2.destroyAllWindows()                     # 열린 모든 윈도우 제거​

(출처 : opencv-python으로 배우는 영상 처리 및 응용)

 

- cv2.rectangle(),  cv2.putText(), cv2.circle()

사각형을 그리는 함수, 글을 쓰는 함수, 원을 그리는 함수입니다.

 

- 사각형은 좌상단의 점의 좌표, 우하단의 점의 좌표입니다.

- 글자를 쓸 때는 폰트나 크기, 굵기 등을 정할 수 있습니다.

- 원은 중심과 반지름을 주면 됩니다.

 

3. 산술연산과 히스토그램

- 산술연산

픽셀들에 적당한 값을 더해주면 이미지 자체의 밝기를 낮출 수 있습니다. 왜냐하면 검은색은 255이기 때문!

 

그렇다면 곱하기는? 그 차이가 증가합니다.

예를들어 두 픽셀이 각각 10과 20의 값을 가졌다고 해보자. 이 때 두 값에 x2를 동시에 해준다면 값은 20 40이 됩니다.

원래 차이는 10 이었는데 차이가 20으로 바뀌었습니다.

 

차이가 늘어났다는건? 이미지의 선명도가 늘어난다는 뜻.

(그러나 대비는 똑같다, 궁금하면 식의 각 값에 a배를 해볼 것, 그런데 또 사실 255에 도달해버리면 연산 방식에 따라 복잡해질 수도 있다.)

 

- 히스토그램

각 픽셀마다의 값을 0~255까지 세어서 히스토그램을 그릴 수 있습니다.

히스토그램은 굉장히 중요하게 사용되는 도구로서 이미지의 대강을 파악할 수 있습니다.

 

결국은 우리는 히스토그램이 고르게 퍼져 있게 하는 것이 목적입니다.

대비가 작거나 한쪽으로 편향되어 있는 히스토그램을 위에서 배운 산술연산을 통해 고르게 퍼져있게 합니다. 그래야 눈에 잘보이거든요.(Histogram Stretching)

 

import numpy as np,cv2
import os
import matplotlib.pyplot as plt
os.chdir('개인연습')

image = cv2.imread("pixel.jpg", cv2.IMREAD_GRAYSCALE)

if image is None : raise Exception("영상파일 읽기 오류")

hist = cv2.calcHist([image],[0],None,[32],[0,256]).flatten()

cv2.imshow("image",image)

plt.bar(list(range(32)),hist)
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()

책에는 뭐 귀찮게스리 이상한 코드를 써놨길래 제가 다시 썼습니다. 히스토그램이 잘 보여요.

 

[os.chdir은 이미지가 있는 폴더로 이동하는 코드이고 / cv.imread는 그 이미지 파일을 읽어주는 코드입니다.]

 

요건 히스토그램의 대비가 크지 않을 때 넓혀주는 수식

4. Threshold

CV2.threshold(src, thresh, maxval, type, dst= None) -> retval, dst

임계값을 주고 그 임계값을 넘으면 어떤 값으로, 임계값보다 작으면 또 다른 값으로 매칭해주는 함수입니다.

src는 이미지 넣어주는 부분이고,

maxval은 threshold를 넘어서면 설정하는 값을(근데 왜 minval은 없지...?),

type은 아래 이미지에 적힌 것과 같이 어떤 방식으로 threshold를 사용할지에 대한 변수입니다.

출처 : https://deep-learning-study.tistory.com/223

 

import numpy as np,cv2
import os
os.chdir('개인연습')

image = cv2.imread("arrow3.png", cv2.IMREAD_GRAYSCALE)

if image is None : raise Exception("영상파일 읽기 오류")

_,image_t = cv2.threshold(image,0,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU)

cv2.imshow('original',image)
cv2.imshow('thresh',image_t)

cv2.waitKey(0)
cv2.destroyAllWindows()

화살표 이미지에 생각보다 잘 안된다. 확실히 구분될때야 말로 잘 되는 듯합니다.