[openCV] ROI
openCV

[openCV] ROI

이번에는 전에도 종종 기술되었던 ROI를 정리를 해보려고 한다.

 


Region Of Interest

 

이미지 내 관심 영역 지정


단어 약자에서도 볼 수 있듯이 이미지 내에서

사용자가 원하는 구간만 추출할 수 있는 기능 중 하나이다.

 

openCV에서 image를 load하는 경우 또는 video를 capture할때에

pixel 단위로 numpy array에 저장하기 때문에

우리는 이를 이용해서 특정 position에 접근하여서

crop과 같은 다양한 행위를 해준다고 생각하면 될 거 같다.

 

 

 

1. Real_Time_ROI

 

import cv2

#Check The Pressing Status Of Mouse
mouse_is_pressing = False
#Reset The Value
start_x, end_x, start_y, end_y = 0,0,0,0
#Check The Event Status
step = 0
temp = 0
#Swap The Position
def swap(v1, v2):
    global temp
    temp = v1
    v1 = v2
    v2 = temp

#Press The Left Button Of Mouse == Start Position Of ROI
#Release The Left Button Of Mouse == End Position Of ROI
#If Moving The Mouse And Draw Rectangle By ROI Region
def Mouse_Callback(event, x, y, flags, param):
    global step, start_x, end_x, start_y, end_y, mouse_is_pressing

    #Press The Left Button
    if event == cv2.EVENT_LBUTTONDOWN:
        step = 1
        mouse_is_pressing = True
        start_x = x
        start_y = y
    
    #Moving The Mouse
    elif event == cv2.EVENT_MOUSEMOVE:
        #If Pressing The Mouse
        if mouse_is_pressing:
            end_x = x
            end_y = y
            step = 2
    #Release The Left Button
    elif event == cv2.EVENT_LBUTTONUP:
        mouse_is_pressing = False

        end_x = x
        end_y = y

        step = 3

cap = cv2.VideoCapture(0)

if cap.isOpened() == False:
    print("Cant Open The Camera")
    exit(-1)

cv2.namedWindow("Color")
#cv2.setMouseCallback(windowName, onMouse, param = None)
#windowName = Dispose Of The Mouse Event in Window
#onMouse = Call Back Function
#param = Data of CallBack Function's Argument
cv2.setMouseCallback("Color", Mouse_Callback)

while True:

    ret, img_color = cap.read()

    if ret == False:
        print("Cant Load The Camera")
        break

    #Press The Left Button
    if step == 1:
        cv2.circle(img_color , (start_x, start_y), 10, (0, 255, 0), -1)

    #Moving The Mouse
    elif step == 2:
        cv2.rectangle(img_color, (start_x, start_y), (end_x, end_y), (0, 255, 0), 3)

    #Release Of The Mouse
    elif step == 3:
        #If Start X Position Is Bigger Than End X
        if start_x > end_x:
            
            swap(start_x, end_x)
            swap(start_y, end_y)

        
        ROI = img_color[start_y : end_y, start_x : end_x]

        ROI = cv2.cvtColor(ROI, cv2.COLOR_BGR2GRAY)
        ROI = cv2.Canny(ROI, 150, 50)
        ROI = cv2.cvtColor(ROI, cv2.COLOR_GRAY2BGR)

        img_color[start_y : end_y, start_x : end_x] = ROI

    cv2.imshow("Color", img_color)

    key = cv2.waitKey(1)

    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()

이 코드는 웹캠 영상에서 마우스를 이용하여서 

ROI Region을 설정한 후에 해당 Region에만 Canny Edge 검출을 하는 코드이다.

 

2021/01/16 - [openCV] - [openCV] Graphic User Interface

 

[openCV] Graphic User Interface

제목에 쫄지 말자 그저 GUI의 Full Name일뿐😬 우선 오늘은 제목에 나와 있듯이 openCV에서 지원하는 GUI를 다뤄보면서 공부해보자 0. What Is Canny Edge? 코드를 보기 전에 Canny Edge가 뭔지 알아보자🤔 Cann

confidence-10211.tistory.com

Canny Edge에 대해서는 위 글에 설명이 되어있다.

 

코드가 전보다 길어졌지만 하나 하나 살펴보자

 

#Check The Pressing Status Of Mouse
mouse_is_pressing = False
#Reset The Value
start_x, end_x, start_y, end_y = 0,0,0,0
#Check The Event Status
step = 0

mouse_is_pressing은 mouse의 pressing status를 체크할 수 있는 변수이다.

start x, y / end x, y는 대충 봐도 알 수 있겠지만 Position들을 담을 변수이다.

step은 밑에 함수를 보면 이해가 갈텐데 현재 mouse의 status를 판단하여서

코드의 flow를 유동적으로 바꿔주는 역할을 한다.

 

 

#Press The Left Button
    if event == cv2.EVENT_LBUTTONDOWN:
        step = 1
        mouse_is_pressing = True
        start_x = x
        start_y = y

이제 CallBack 함수의 일부분을 살펴볼건데

 

cv2.EVENT_LBUTTONDOWN = window에서 왼쪽 마우스 버튼이 눌릴 경우

 

만약 왼쪽 마우스가 눌린다면

step에 1을 대입하고

마우스가 눌렸으니 mouse_is_pressing을 True로 바꿔준다.

start x, y에는 클릭 시 (x, y) 좌표를 대입한다.

 

 #Moving The Mouse
    elif event == cv2.EVENT_MOUSEMOVE:
        #If Pressing The Mouse
        if mouse_is_pressing:
            end_x = x
            end_y = y
            step = 2

cv2.EVENT_MOUSEMOVE = window에서 마우스가 움직일 경우

 

 

만약 마우스가 움직이면서, 마우스가 눌린 상태라면

end x,y에 현재 마우스 커서가 존재하는 좌표들을 넣어준다.

step에 2를 대입한다.

 

#Release The Left Button
    elif event == cv2.EVENT_LBUTTONUP:
        mouse_is_pressing = False

        end_x = x
        end_y = y

        step = 3

cv2.EVENT_LBUTTON = window에서 왼쪽 마우스 버튼에서 Release 했을 경우

 

마우스에서 Release가 된 경우 mouse_is_pressing에 False를 대입해준다.

 

그 후 최종적으로 end x, y에 현재의 좌표를 대입한다.

 

 

#cv2.setMouseCallback(windowName, onMouse, param = None)
#windowName = Dispose Of The Mouse Event in Window
#onMouse = Call Back Function
#param = Data of CallBack Function's Argument
cv2.setMouseCallback("Color", Mouse_Callback)

cv2.setMouseCallback( windowName, onMouse(callBack Function), param )

 

setMouseCallBack 함수를 이용해서 미리 생성해둔 window에서

Mouse Event를 이용할 수 있도록 한다

 

cv2.setMouseCallback 함수의 Argument 중 param은

callBack Function에 parameter을 넘겨줄 떄 사용한다.

만약 param이 None status라면 아무런 parameter을 넘겨주지 않는다.

 

#Press The Left Button
    if step == 1:
        cv2.circle(img_color , (start_x, start_y), 10, (0, 255, 0), -1)

위에서 step이 1인 경우는 마우스의 왼쪽 버튼을 클릭하였을 때이므로

마우스가 클릭되었다는것을 시각적으로 표기하기 위해서

원을 그려줄 수 있도록 하였다.

 

#Moving The Mouse
    elif step == 2:
        cv2.rectangle(img_color, (start_x, start_y), (end_x, end_y), (0, 255, 0), 3)

step이 2인 경우는 마우스가 움직이는 상태이므로

ROI 영역을 사용자에게 표기하여 주기 위해서

rectangle 함수를 이용한다.

 

#Release Of The Mouse
    elif step == 3:
        #If Start X Position Is Bigger Than End X
        if start_x > end_x:

            swap(start_x, end_x)
            swap(start_y, end_y)

        
        ROI = img_color[start_y : end_y, start_x : end_x]

        ROI = cv2.cvtColor(ROI, cv2.COLOR_BGR2GRAY)
        ROI = cv2.Canny(ROI, 150, 50)
        ROI = cv2.cvtColor(ROI, cv2.COLOR_GRAY2BGR)

        img_color[start_y : end_y, start_x : end_x] = ROI

step이 3인 경우는 ROI 영역을 사용자가 지정하였다는 것이다.

 

여기서 예외처리를 하나 해줬다.

 

만약 시작 좌표가 마무리 좌표보다 큰 경우에는

swap 함수를 이용하여서 서로의 좌표를 바꿔주었다.

 

한마디로 드래그 방향이

위와 같지 않고

 

드래그의 방향이 위 그림과 같아지면

swap 함수가 실행이 되는것이다.

 

그 후 ROI 영역에 Canny edge를 적용해준다.

 

 

 

2. Operate_ROI_Average_Color

 

이번에는 ROI 영역에 평균 색을 추출하는 코드이다.

 

import cv2
import numpy as np 

cap = cv2.VideoCapture(0)

while True:
    ret, img_color = cap.read()
    img_result = img_color.copy()

    height, width = img_color.shape[:2]

    center_x = int(width * 0.5)
    center_y = int(height * 0.5)

    cv2.rectangle(img_result, (center_x - 100, center_y - 100), (center_x + 100, center_y + 100), (0, 0, 255), 3)

    img_roi = img_color[center_y - 100 : center_y + 100, center_x - 100 : center_x + 100]

    m = cv2.mean(img_roi)

    img_mean = np.zeros(img_roi.shape, dtype=np.uint8)
    img_mean[:]  = (m[0], m[1], m[2])

    cv2.imshow('mean', img_mean)
    cv2.imshow('color', img_result)
    cv2.imshow("roi", img_roi)

    key = cv2.waitKey(1)

    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()

 

코드 자체는 그리 길지 않으나 처음 보는 메소드가 존재해서

하나씩 살펴보려고 한다.

 

height, width = img_color.shape[:2]

사진의 전체 높이와 너비 대입

 

center_x = int(width * 0.5)
center_y = int(height * 0.5)

Center Postion 구하기

 

img_roi = img_color[center_y - 100 : center_y + 100, center_x - 100 : center_x + 100]

ROI Region 지정

 

m = cv2.mean(img_roi)

cv2.mean(img, mask = mask)

 

cv2.mean()은 평균 color값을 찾을 때 사용하는 메소드이며

평균 intensity 값을 찾을 때 사용한다.

 

img_mean = np.zeros(img_roi.shape, dtype=np.uint8)
img_mean[:]  = (m[0], m[1], m[2])

img_mean에 세로운 넘파이 배열을 만들어준다.

그리고 img_mean의 색상을 위해서 구했던 color의 average 값을

BGR에 대입을 해준다.

 

cv2.imshow('mean', img_mean)
cv2.imshow('color', img_result)
cv2.imshow("roi", img_roi)

각 결과 출력

 

흐어ㅓㅓㅓㅓ 요즘에 너무 힘들다

할 게 너무 많아졌다

 

오늘도 끄읕😑