본문 바로가기

딥러닝(Deep Learning)/OpenCV-Python

cv.namedWindow, cv.setMouseCallback의 관계(Feat, winname, 윈도우 창 구분자)

 

import cv2 as cv
import numpy as np
import sys


img = cv.imread("2.jpg")

if img is None:
    sys.exit("해당 파일을 찾지 못하였습니다.")
    

def drawing(event,x,y,flags,param):

    global ix,iy  
    

    if event == cv.EVENT_LBUTTONDOWN:
        ix,iy = x,y

    elif event == cv.EVENT_RBUTTONUP:
        cv.rectangle(img,(ix,iy),(x,y),(0,0,255),2)

    print("x",x,"y",y)
    
    cv.imshow("t2",img)


cv.namedWindow("t1")
cv.imshow("t1",img)

cv.setMouseCallback("tittle",drawing)



while True:
    if cv.waitKey(1) == ord('q'):
        cv.destroyAllWindows()
        break

 

여태까지 cv.imshow(), cv.namedWindow(), cv.setMouseCallback()의 첫번째 인수에 대해 큰 고민을 해보지 않고 그냥 사용

해 왔다. 

그럼, 위 코드대로 실행한 결과는 어떨까?

그림 1

 

위와 같은 에러 메시시가 뜬다. 

이는 나의 cv.imshow(), cv.namedWindow(), cv.setMouseCallback() 함수에 대한 미숙지의 결과이다. 

우선, cv.namedWindow()에 대해서 먼저 살펴보자

cv2.namedWindow(winname, flags) 함수는 winname이라는 이름을 갖는 창을 생성해줍니다.

파라미터는 아래와 같습니다.

winname: 창 구분자 활용될 창 이름(즉, 여러 개의 Window 창이 있을 경우, 특정 Window를 지정하기 위한 ID)


flags: 창 옵션 (cv2.WINDOW_NORMAL: 사용자가 창 크기를 조정할 수 있음, cv2.WINDOW_AUTOSIZE: 이미지와 동일한

크기로 창 크기를 재조정할 수 없음)

import cv2

file_path = '../img/yeosu.jpg'
img = cv2.imread(file_path)                            # 이미지를 기본 값으로 읽기
img_gray = cv2.imread(file_path, cv2.IMREAD_GRAYSCALE) # 이미지를 그레이 스케일로 읽기

cv2.namedWindow('origin')                               # [origin 이라는 구분자로 창] 생성
cv2.namedWindow('gray', cv2.WINDOW_NORMAL)              # [gray 이라는 구분자로 창] 생성
cv2.imshow('origin', img)                               # [origin window 창]에 이미지 표시
cv2.imshow('gray', img_gray)                            # [gray window 창]에 이미지 표시

cv2.moveWindow('origin', 0, 0)                          # [origin Window 창] 위치 변경
cv2.moveWindow('gray', 100, 100)                        # [gray Window 창] 위치 변경

cv2.waitKey(0)                                          # 아무키나 누르면
cv2.resizeWindow('origin', 200, 200)                    # [origin Window 창] 크기 변경 (변경 안됨)
cv2.resizeWindow('gray', 100, 100)                      # gray Window 창 크기 변경 (변경 됨))

cv2.waitKey(0)                                          # 아무키나 누르면
cv2.destroyWindow("gray")                               # [gray window] 창 닫기.모든 window 창이 아닌 [특정 window 창]만 닫기

cv2.waitKey(0)                                          # 아무키나 누르면
cv2.destroyAllWindows()                                 # 모든 창 닫기

마치 html 태그 안의 id 속성 값처럼 cv.namedWindow()의 winname 매개변수가 사용된다. 

고로, 예를 들어, cv2.namedWindow('gray')라는 gray를 구분자로 하여 윈도우 창을 생성해 주는 함수를 실행을 하고

그 아래에서 cv2.imshow("gray",img)라는 명령어를 실행을 하게 되면, imshow()의 "gray"라는 구분자를 이용하여  여러 개

의 window 창 중에 title이 "gray"인 window 창에 img를 띄우게 된다. 

또한 cv2.destroyWindow("gray")를 하게 되면, cv2.destroyAllWindows()와 달리 여러 개의 window 창 중, 구분자로

"gray"를 가지고 있는 특정한 window 창만을 닫게 해 준다. 

실제로, 아래와 같은 window 창을 켜서 어떠한 GUI 기능을 하는 OpenCV의 함수들은 반드시 winname이라는 매개변수를

필요로 한다. 

cv2.moveWindow(winname, x, y) 함수를 호출하면 원하는 위치로 창을 옮길 수 있습니다.

winname: 위치를 변경할 창 이름
x, y: 변경할 위치 (x, y 좌표)

cv2.resizeWindow(winname, width, hegith) 함수는 winname 창의 크기를 (width, height) 크기로 변경해줍니다.

cv2.destroyWindow(winname) 함수를 호출하면 winname에 해당하는 창을 닫습니다.

(위 메서드에 대해서는 아래 사이트 참조)

https://bkshin.tistory.com/entry/OpenCV-5-%EC%B0%BD-%EA%B4%80%EB%A6%AC-%EB%B0%8F-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%B2%98%EB%A6%AC

 

OpenCV - 5. 창 관리 및 이벤트 처리

이번 포스팅에서는 창을 관리하는 방법과 키보드 및 마우스 이벤트를 처리하는 방법을 알아보겠습니다. 이번 글 역시 파이썬으로 만드는 OpenCV 프로젝트(이세우 저)를 정리한 것입니다. 코드: htt

bkshin.tistory.com

위의 내용들을 이해했다면, 젤 위에 있는 나의 코드에 어떤 문제가 있는지 알 수가 있을 것이다. 

import cv2 as cv
import numpy as np
import sys


img = cv.imread("2.jpg")

if img is None:
    sys.exit("해당 파일을 찾지 못하였습니다.")
    

def drawing(event,x,y,flags,param):

    global ix,iy  
    

    if event == cv.EVENT_LBUTTONDOWN:
        ix,iy = x,y

    elif event == cv.EVENT_RBUTTONUP:
        cv.rectangle(img,(ix,iy),(x,y),(0,0,255),2)

    print("x",x,"y",y)
    
    cv.imshow("t2",img)


cv.namedWindow("t1")
cv.imshow("t1",img)

cv.setMouseCallback("tittle",drawing) # "tittle"이라는 window 창 구분자가 없음



while True:
    if cv.waitKey(1) == ord('q'):
        cv.destroyAllWindows()
        break

주석에도 달아 놓았지만, setMouseCallback("tittle"...)에서 마우스 이벤트를 등록할 window 창을 지정해주느 부분인

첫번째 인수에 'tittle"이라는 window 창 구분자를 지정해 준 꼴인데, 그러나 나는 그 어디에도 "tittle"이라는 window 창을 

만들어 주지 않았다. 

그래서, 아래와 같은 에러 메시지가 발생을 한 것이다. 

그림 1

이 에러를 해결하기 위해서는 코드를 아래와 같이 수정하면 된다. 

import cv2 as cv
import numpy as np
import sys


img = cv.imread("2.jpg")

if img is None:
    sys.exit("해당 파일을 찾지 못하였습니다.")
    

def drawing(event,x,y,flags,param):

    global ix,iy  
    

    if event == cv.EVENT_LBUTTONDOWN:
        ix,iy = x,y

    elif event == cv.EVENT_RBUTTONUP:
        cv.rectangle(img,(ix,iy),(x,y),(0,0,255),2)

    print("x",x,"y",y)
    
    cv.imshow("t1",img) # 수정


cv.namedWindow("t1")
cv.imshow("t1",img)

cv.setMouseCallback("t1",drawing) # "t1"으로 수정-> window 창 "t1"에만 콜백함수를 지정



while True:
    if cv.waitKey(1) == ord('q'):
        cv.destroyAllWindows()
        break