[KDT_AISEC] 7주차 - openCV(1)

Gloomy·2024년 2월 6일
0

KDT_AISEC

목록 보기
22/25

OpenCV


OpenCV란?

OpenCVOpen Source Computer Vision의 약자로, 영상 처리에 사용할 수 있는 오픈 소스 라이브러리이다. 개인정보 비식별 트랙의 목적은 단순히 정형화된 자료를 비식별 처리하는것이 아니라 이미지나 영상등의 데이터도 비식별 처리를 하는것이 목적이다.

따라서 OpenCV를 이용해 해당 처리를 수행하기 위한 기반을 쌓아보자.

이미지 읽고 쓰기

import cv2 as cv

cv.__version__
'4.9.0'

우선 OpenCV의 버전은 가장 최신 버전을 사용하였다. 이미지를 불러와보자

img = cv.imread('../samples/starry_night.jpg')

if img is None:
    print("Not Found")

img[0].shape
(752, 3)

이미지를 불러온 후 shape을 확인해보니 RGB 3채널로 이루어진 이미지임을 확인할 수 있다.
이미지를 출력해보자.

cv.imshow("Display Window", img)
k = cv.waitKey(0)


성공적으로 출력되는것을 확인할 수 있다. 여기서 waitKey는 키 핸들러 함수인데, 키의 입력을 기다리다가 해당 키를 입력하면 그 키의 아스키 값이 k에 저장된다.
이제 이미지를 저장해보자.

cv.imwrite('starry_night_1.jpg', img)

성공적으로 저장되었다.

비디오 및 웹캠 실행하기

videoFile = '../samples/vtest.avi'

cap = cv.VideoCapture(videoFile)

while(cap.isOpened()):

    ret, frame = cap.read()

    # frame 조작

    if ret:
        cv.imshow('video', frame)

        if cv.waitKey(1) & 0xFF == ord('q'):
            break

    else:
        break

cap.release()
cv.destroyAllWindows()

위의 코드는 vtest.avi를 실행하는 코드이다. waitKey를 이용해 q가 입력되면 종료하도록 했다.

cap = cv.VideoCapture(0)

if not cap.isOpened():
    print("Cannot open camera")

while True:

    ret, frame = cap.read()

    if not ret:
        break

    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)

    cv.imshow('cam', gray)
    if cv.waitKey(1) == ord('q'):
        break

cap.release()
cv.destroyAllWindows()

웹캠을 실행시킨 후 그레이 스케일(흑백 이미지)로 출력한다. 마찬가지로 waitKey를 이용해 q가 입력되면 종료하도록 했다.

웹캠을 가려놓아 제대로 보이지는 않지만 잘 실행되는것을 볼 수 있다.

도형 그리기

drawing = False # 마우스를 누른 상태에서는 True 값을 가짐
mode = True # True라면 사각형을 그리는 모드 m을 눌러 모드 변경 가능
ix,iy = -1,-1

# 마우스 콜백 함수
def draw_circle(event,x,y,flags,param):
    global ix,iy,drawing,mode
    
    if event == cv.EVENT_LBUTTONDOWN:
        drawing = True
        ix,iy = x,y
    elif event == cv.EVENT_MOUSEMOVE:
        if drawing == True:
            if mode == True:
                cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
            else:
                cv.circle(img,(x,y),5,(0,0,255),-1)
    elif event == cv.EVENT_LBUTTONUP:
        drawing = False
        if mode == True:
            cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
        else:
            cv.circle(img,(x,y),5,(0,0,255),-1)

            
img = np.zeros((512,512,3), np.uint8)
cv.namedWindow('image')
cv.setMouseCallback('image',draw_circle)

while(1):
    cv.imshow('image',img)
    k = cv.waitKey(1) & 0xFF
    
    # 모드 변경
    if k == ord('m'):
        mode = not mode
    elif k == 27:
        break
cv.destroyAllWindows()

사각형과 원을 그리는 코드이다. m키를 토글해서 사각형과 원을 그리는 모드를 변경할 수 있고, 빈 윈도우에 마우스를 이용해 그림을 그릴 수 있다.


도형뿐만 아니라 폴리곤과 선 등도 그릴 수 있다.

트랙바

def nothing(x):
    pass

cv.namedWindow('image')
cv.createTrackbar('R', 'image', 0, 255, nothing)
cv.createTrackbar('G', 'image', 0, 255, nothing)
cv.createTrackbar('B', 'image', 0, 255, nothing)

switch = "0: OFF \n1: ON"
cv.createTrackbar(switch, 'image', 0, 1, nothing)

while True:
    cv.imshow('image', img)
    k = cv.waitKey(1) & 0xFF
    if k == 27:
        break
    r = cv.getTrackbarPos('R', 'image')
    g = cv.getTrackbarPos('G', 'image')
    b = cv.getTrackbarPos('B', 'image')
    s = cv.getTrackbarPos(switch, 'image')

    if s == 0:
        img[:] = 0
    else:
        img[:] = [b, g, r]

cv.destroyAllWindows()

트랙바를 이용해 RGB의 값에 따라 아래 패널의 색을 조절하는 코드이다. 가장 아래는 스위치를 넣어 기능을 ON/OFF 할 수 있게 했다.

ROI

ROI는 아주 중요한 개념이다. ROIRegion Of Interest의 약자로, 이미지나 영상에서 임의의 작업을 처리하기 위해 연산을 수행하려는 부분의 영역을 의미한다.

img = cv.imread('../samples/messi5.jpg')

plt.imshow(img)

우선 축구선수 메시의 이미지를 불러와보자.

우리는 공에 초록색으로 사각형을 그리려고 한다.
그렇다면 관심 영역(ROI)는 어디일까?

ball = img[280:340, 330:390] # x, y, w, h (280, 330, 60, 60)
plt.imshow(ball)

해당 부분이 ROI라고 할 수 있다.
그렇다면 cv.rectangle을 이용해 그림을 그려보자.

# 사각형
# cv.rectangle(img, 좌측상단코너 좌표, 우측하단코너 좌표, 색상, 굵기)
cv.rectangle(img, (330, 280), (390, 340), (0, 255, 0), 3)

plt.imshow(img)


이처럼 특정 부분을 지정해 임의의 작업을 수행하게 되는데, 이 과정에서 지정하는 영역을 ROI라고 한다.

ROI Selector

img2 = img.copy()

rois = []
drawing = False
ix, iy = -1, -1

def draw_rectangle(event, x, y, flags, param):
    
    global drawing, ix, iy, rois, overlay, output, alpha
    
    overlay = img.copy()
    output = img.copy()
    alpha = 0.5
        
    if event == cv.EVENT_LBUTTONDOWN:
        drawing = True
        ix, iy = x, y
        
    elif event == cv.EVENT_MOUSEMOVE:
        if drawing == True:
            cv.rectangle(overlay, (ix, iy), (x, y), (0, 255, 0), 3)
            cv.addWeighted(overlay, alpha, output, 1-alpha, 0, img2)
            cv.imshow('image', img2)
    
    elif event == cv.EVENT_LBUTTONUP:
        if drawing == True:
            print('레이블 입력하세요',)
            label = input()
            w = x - ix 
            h = y - iy
            r = [ix, iy, w, h, label]
            rois.append(r)
            print(rois)
        
        cv.rectangle(overlay, (ix, iy), (x, y), (0, 255, 0), 3)
        cv.addWeighted(overlay, alpha, output, 1-alpha, 0, img)
        
        drawing = False
        ix, iy = -1, -1

cv.namedWindow('image')
cv.setMouseCallback('image', draw_rectangle)

while(1):
    cv.imshow('image', img)
    k = cv.waitKey(1) & 0xFF
    
    if k == 27:
        break

cv.destroyAllWindows()

그리기 함수와 ROI를 접목해 다음과 같이 이미지에서 라벨링하는 프로그램도 만들 수 있다. 마우스 이벤트 핸들러를 이용해서 각각의 마우스 버튼의 UP, DOWNMOVE를 감지하고 알맞은 코드를 실행할 수 있다. 위의 코드는 왼쪽 마우스 버튼이 눌리면 그리기 모드로 전환하고 움직이는 동안 임시 이미지에 사각형을 그려서 더하는 과정을 보여준다. 그리고 왼쪽 마우스 버튼을 떼면 레이블 이름과 해당 좌표값등의 정보를 입력받고 마지막으로 ROI를 표시해서 본 이미지에 나타내준다.

profile
𝙋𝙤𝙨𝙨𝙤 𝙁𝙖𝙧𝙚!

0개의 댓글