OpenCV
란 Open 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
는 Region 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
라고 한다.
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
, DOWN
과 MOVE
를 감지하고 알맞은 코드를 실행할 수 있다. 위의 코드는 왼쪽 마우스 버튼이 눌리면 그리기 모드로 전환하고 움직이는 동안 임시 이미지에 사각형을 그려서 더하는 과정을 보여준다. 그리고 왼쪽 마우스 버튼을 떼면 레이블 이름과 해당 좌표값등의 정보를 입력받고 마지막으로 ROI
를 표시해서 본 이미지에 나타내준다.