Basic Image with OpenCV

박광욱·2023년 1월 14일
0

Computer Vision

목록 보기
2/8

📕 OpenCV를 사용하여 이미지 불러오기

내장 라이브러리

import cv2

이미지 불러오기

# 경로를 잘못 입력해도 오류가 나지 않는다. NoneType이라고 명시할 뿐
img = cv2.imread('YOUR IMAGE DIRECTION')
# cv2를 사용하면 numpy배열로 바꾸어주는 작업이 한번에 진행됨
type(img)

💻 결과

numpy.ndarray

위의 함수를 사용하면 numpy배열로 바꾸어 주기 때문에 변환에 용이하다.


RGB바꾸기

# matplotlib에서는 RGB순서로 읽는다.
# 하지만 cv2에서는 BGR순서로 읽기때문에 색이 이상해짐
plt.imshow(img)
fix_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(fix_img)

💻 결과


matplot을 사용하면 RGB순서대로 나오지만 cv2를 사용하면 BGR순서로 나오기 때문에 색을 바꾸어 주는 작업을 해주어야한다.


이미지를 흑백으로 불러오기

img_gray = cv2.imread('YOUR IMAGE DIRECTION', cv2.IMREAD_GRAYSCALE)
img_gray.shape
plt.imshow(img_gray, cmap='gray')

💻 결과

(1300, 1950)

위의 방법으로 불러오면 원래 채널이 3개라서 (1300, 1950, 3)의 형태로 나와야 하지만 1개의 채널로 나오게 된다.
또한 이미지를 출력할 때 Numpy 및 Image Basics에서 나타낸 것 처럼 cmap='gray'가 필수적으로 나와야 한다.


이미지 변형 - 1

fix_img.shape		# (1300, 1950, 3)
# 1900 -> 1000, 1300 -> 400
new_img = cv2.resize(fix_img, (1000, 400))
plt.imshow(new_img)

💻 결과

(1300, 1950)의 크기인 이미지를 (400, 1000)의 크기로 바꾼다.
여기서 주의해야할 점이 함수를 사용할 때에는 행과 열의 위치가 반대이다.


이미지 변형 - 2

w_ratio = 0.5
h_ratio = 0.5
new_img = cv2.resize(fix_img, (0, 0), fix_img, w_ratio, h_ratio)
plt.imshow(new_img)

💻 결과

고정된 값으로만 크기를 바꿀수 있는 것이 아닌 비율로도 변환이 가능하다.


이미지 변형 - 3

new_img = cv2.flip(fix_img, 0) # 상하로 반전
new_img = cv2.flip(fix_img, 1) # 좌우로 반전
new_img = cv2.flip(fix_img, -1) # 상하좌우 반전
plt.imshow(new_img)

💻 결과

또 이미지를 뒤집는 경우도 있다. flip 함수에 0을 넣으면 상하로 뒤집히고, 1을 넣으면 좌우, -1을 넣게 되면 상하좌우가 바뀌게 된다. 위의 결과는 마지막에 있는 -1이 들어가있는 함수가 실행 되기 때문에 상하좌우가 바뀐 이미지가 나왔다.


📗 이미지를 새 창에서 띄우기

이미지를 새 창에서 띄우기

import cv2
img = cv2.imread('YOUR IMAGE DIRECTION')
while True:
    cv2.imshow('Puppy', img)
    # 1ms를 기다리고 esc버튼을 눌렀다면 멈춤
    if(cv2.waitKey(1) & 0xFF == 27):
        break
cv2.destroyAllWindows()

새 창에서 이미지를 띄우는 방법으로 cv2.imshow함수는 첫 번째 인자가 제목이고 두 번째 인자는 띄울 이미지이다.
if문을 보면 cv2.waitKey(1)의 함수는 1ms만큼 기다리겠다는 의미이고 0xFF == 27의 의미는 ESC버튼을 누른다는 의미이다.
cv2.destroyAllWindows()의 함수는 현재 띄어진 화면들을 모두 없애는 함수이다.
위의 코드를 실행하게되면 ESC를 눌러야지 화면에 띄어진 이미지가 없어진다.
이렇게 새 창에서 이미지를 나타나게하면 이미지의 크기를 변경할순 없다.


📘 이미지에 도형 그리기

  • 도형을 그리는 작업을 해주는 이유는 나중에 이미지를 읽고 나서 객체의 위치를 나타낼 때 보통 직사각형안에 해당 객체를 표현하게 된다.

직사각형 그리기

blank_img = np.zeros((512, 512, 3), dtype = np.int16)	# 검은 이미지 생성
# pt1 : 왼쪽 위
# pt2 : 오른쪽 아래
# thickness : 몇 픽셀만큼 두께
cv2.rectangle(blank_img, pt1 = (384, 10), pt2 = (500, 150), color=(0, 255, 0), thickness=10)
plt.imshow(blank_img)

💻 결과

Numpy 및 Image Basics에서 사용한 np.zeros함수를 사용해 검은 화면에 직사각형을 그린다.
cv2.rectangle의 함수는 이미지, 좌표 2개, 색, 굵기가 매개변수로 들어간다.
pt1의 좌표는 왼쪽 위, pt2의 좌표는 오른쪽 아래 이 두가지만 있으면 직사각형을 그릴 수 있다.


원 그리기

cv2.circle(blank_img, center=(100,100), radius=50, color=(0,0,255), thickness=8)
plt.imshow(blank_img)

💻 결과

cv2.circle의 함수도 직사각형을 그릴 때와 별 차이점 없이 이미지, 좌표, 반지름, 색, 굵기가 매개변수로 들어가게 된다.


선 그리기

cv2.line(blank_img, pt1=(100,400), pt2=(500, 460), color=(255,255,255), thickness=5)
plt.imshow(blank_img)

💻 결과

선을 그리는 함수도 이미지, 좌표 2개, 색, 굵기를 매개변수로 가진다.


색이 채워진 도형 그리기

cv2.circle(blank_img, center=(100,100), radius=50, color=(0,0,255), thickness=-1)
plt.imshow(blank_img)

💻 결과

색이 채워진 도형을 그리기 위해선 선의 굵기를 나타내는 thickness부분에 -1을 넣으면 된다.


사용자 정의로 도형 그리기

vertices = np.array([ [100,300], [200,200], [400,300], [200,400] ], dtype = np.int32)
# 이미지는 대부분 3차원인데 현재 vertices의 차원은 2차원 이므로 늘려준다
pts = vertices.reshape((-1,1,2))
cv2.polylines(blank_img, [pts], isClosed=True, color=(0,0,255), thickness=5)
plt.imshow(blank_img)

💻 결과

사용자 정의대로 도형을 나타내려면 일단 원하는 좌표를 만들어준다.
하지만 좌표가 들어있는 배열은 2차원이고 이미지는 3차원 이므로 좌표 배열의 차원을 바꾸어준다.
(-1, 1, 2)로 reshape를 해주면 배열이 (4, 2)에서 (4, 1, 2)으로 차원이 커지게 된다.
채워진 도형을 그리고 싶다면 cv2.fillPoly함수를 사용하면된다.


이미지에 글씨 쓰기

font = cv2.FONT_HERSHEY_SIMPLEX
# org : 왼쪽 아래 좌표
# lineType : 선의 종류
cv2.putText(blank_img, text='Hello', org=(10,500), fontFace=font, fontScale=4, color=(255,255,255), thickness=3, lineType=cv2.LINE_AA)
plt.imshow(blank_img)

💻 결과

이 경우는 인자로 이미지, 텍스트, 텍스트를 나타낼 좌표(왼쪽 아래), 폰트, 색, 굵기, 선 타입 등 많은 매개변수가 들어간다.


📙 마우스를 이용해 도형 그리기

마우스를 이용해 도형 그리기

import cv2
import numpy as np
################
### FUNCTION ###
################
def draw_circle(event, x, y, flags, param):
    """
    원을 그리는 함수
        Args:
            event: 마우스의 클릭 이벤트
            x: 마우스의 좌표
            y: 마우스의 좌표
            flags: 경고 플래그 필요한 경우
            param: 추가 매개변수 있으면 사용
    """
    # 마우스 왼쪽 버튼 클릭 시 (누를 때)
    if(event==cv2.EVENT_LBUTTONDOWN):
        cv2.circle(img, (x,y), 50, (0,255,0), -1)
    elif(event==cv2.EVENT_RBUTTONDOWN):
        cv2.circle(img, (x,y), 30, (255,0,0), -1)
# 같은 이름을 사용해서 서로 연결이 됨
cv2.namedWindow(winname='my_drawing')
cv2.setMouseCallback('my_drawing', draw_circle)
##################################
### SHOWING IMAGE WITH OPEN CV ###
##################################
img = np.zeros((512,512,3), np.int8)
while True:
    cv2.imshow('my_drawing', img)
    if(cv2.waitKey(20) & 0xFF == 27):
        break
cv2.destroyAllWindows()

💻 결과

초록색은 왼쪽 마우스를 클릭 했을 때이고, 파란색은 오른쪽 마우스를 클릭 했을 때 이다.

  • cv2.namedWindow(winname, flags)
    winname: 창 구분자로 활용될 창 이름
    flags: 창 옵션 (cv2.WINDOW_NORMAL: 사용자가 창 크기를 조정할 수 있음, cv2.WINDOW_AUTOSIZE: 이미지와 동일한 크기로 창 크기를 재조정할 수 없음)

  • cv2.setMouseCallback(windowName, onMouse, param=None) -> None
    windowName: 마우스 이벤트 처리를 수행할 창 이름
    onMouse: 마우스 이벤트 처리를 위한 콜백 함수 이름.
    param: 콜백 함수에 전달할 데이터


출처 : cv2.namedWindow, cv2.setMouseCallback, OpenCV 및 딥러닝 을 이용한 Computer Vision 파이썬

profile
Vancouver

0개의 댓글