• Feed
  • Explore
  • Ranking
/
/
    [영상처리프로그래밍]

    #2. OpenCV 인터페이스 기초

    수업정리
    남
    남연진
    2024.09.29
    ·
    9 min read

    1. 윈도우 제어

    OpenCv에서는 윈도우가 활성화된 상태에서만 마우스나 키보드 이벤트를 감지할 수 있다. 따라서 이런 이벤트를 감지해서 처리하려면 윈도우를 생성하고 제어할 수 있어야 한다.

    • cv2.namedWindow(winname [, flags]) : winname으로 윈도우 생성

      • flags

        • cv2.WINDOW_NORMAL : (0) 윈도우 크기 재조정 가능

        • cv2.WINDOW_AUTOSIZE : (1) 표시될 행렬의 크기에 맞춰 자동 조정

    • cv2.imshow(winname, mat) : winname으로 윈도우에 mat행렬을 영상으로 표시한다.

      • 생성된 윈도우가 없으면 winname으로 윈도우를 생성하고 영상을 표시한다.

    • cv2.destroyAllWindows() : HighGUI로 생성된 모드 윈도우를 파괴

    • cv2.destroyWindow(winname) : 인수로 지정된 타이틀의 윈도우를 파괴

    • cv2.moveWindow(winname, x, y) : winname의 윈도우를 지정된 위치인 (x, y)로 이동

    • cv2.resizeWindow(winname, width, height) : 윈도우의 크기를 재조정함

    import cv2
    import numpy as np
    
    image = np.zeros((200, 300), np.unit8) #height, width순서 
    image[:] = 200
    
    title1, title2 = "Position1", "Position2"
    cv2.namedWindow(title1, cv2.WINDOW_AUTOSIZE) #cv2.namedWindow(title)과 똑같음
    cv2.namedWindow(title2, cv2.WINDOW_NORMAL)
    cv2.waitKey(0)
    
    cv2.destroyAllWindows()
    
    >> 기본 창 생성
    import cv2
    import numpy as np
    
    image = np.zeros((200, 300), np.uint8) #height, width순서 
    image[:] = 200
    
    title1, title2 = "Position1", "Position2"
    cv2.namedWindow(title1, cv2.WINDOW_AUTOSIZE) #cv2.namedWindow(title)과 똑같음
    cv2.namedWindow(title2, cv2.WINDOW_NORMAL)
    cv2.waitKey(0)
    
    cv2.moveWindow(title1, 150, 150)
    cv2.moveWindow(title2, 400, 50)
    cv2.waitKey(0)
    
    cv2.destroyAllWindows()
    
    >> 창 움직이기
    import cv2
    import numpy as np
    
    image = np.zeros((200, 300), np.uint8) #height, width순서 
    image[:] = 200
    
    title1, title2 = "Position1", "Position2"
    cv2.namedWindow(title1, cv2.WINDOW_AUTOSIZE) #cv2.namedWindow(title)과 똑같음
    cv2.namedWindow(title2, cv2.WINDOW_NORMAL)
    cv2.waitKey(0)
    
    cv2.imshow(title1, image)
    cv2.imshow(title2, image)
    cv2.waitKey(0)
    
    cv2.destroyAllWindows()
    
    >> 이미지 보이기(image = 200, 연한 회색)

    resize vs AUTOSIZE

    import cv2
    import numpy as np
    
    image = np.zeros((200, 300), np.uint8) #height, width순서 
    image[:] = 200
    
    title1, title2 = "Position1", "Position2"
    cv2.namedWindow(title1, cv2.WINDOW_AUTOSIZE) #cv2.namedWindow(title)과 똑같음
    cv2.namedWindow(title2, cv2.WINDOW_NORMAL)
    cv2.waitKey(0)
    
    cv2.resizeWindow(title1, 600, 300)
    cv2.resizeWindow(title2, 600, 300)
    cv2.waitKey(0)
    
    cv2.destroyAllWindows()
    
    >>resize가 AUTOSIZE보다 쎔 얘가 먹음
    until-1607

    NORMAL로 생성 후 resize하면 이미지가 윈도우 크기에 맞춰 크기가 바뀐다. (캔버스에 맞춤 기능과 유사)

    2. 이벤트 처리

    2.1. 키보드 이벤트

    • waitKey([, delay]) or waitKeyEx([, delay])

      • delay시간만큼 키 입력을 대기하고, 키 이벤트가 발생하면 해당 키 값을 반환한다

        • delay <= 0 : 키 이벤트 발생까지 무한 대기

        • delay > 0 : 지연 시간동안 키 입력 대기, 지연 시간 안에 키 이벤트가 없으며 -1을 반환

      • waitKeyEx는 waitKey와 동일하지만, 전체 키 코드(full key code)를 반환한다. (e.g. 방향키 입력 등에 사용)

    import cv2
    import numpy as np
    
    image = np.zeros((200, 300), np.uint8) #height, width순서 
    cv2.imshow("img1", image)
    
    while True:
        key = cv2.waitKeyEx(100) #ms단위
        if key == 27 : #escape키의 아스키코드값
            break
        elif key == -1 :
            continue
        else :
            if key < 255:
                print(key, chr(key)) #ord vs chr
    
            else : 
                print(key)
    
    cv2.destroyAllWindows()
    
    >> 키값 반환

    2.2. 마우스 이벤트

    마우스 콜백 함수를 사용하여 제어한다.

    • cv2.setMouseCallback(windowName, onMouse, param=None) : 사용자가 정의한 마우스 콜백 함수를 시스템에 등록

    • def onMouse(event, x, y, flags, param = None) : 발생한 마우스 이벤트에 대한 처리와 제어를 구현하는 콜백 함수

    import numpy as np
    import cv2
    
    def onMouse(event, x, y, flags, param):
        if event == cv2.EVENT_LBUTTONDOWN:
            print(" 왼쪽 버튼 누르기")
        elif event == cv2.EVENT_RBUTTONDOWN:
            print("오른쪽 버튼 누르기")
        elif event == cv2.EVENT_RBUTTONUP:
            print("오른쪽 버튼 떼기")
        elif event == cv2.EVENT_LBUTTONUP:
            print("왼쪽 버튼 뗴기")
        
    image = np.full((200, 300), 255, np.uint8)
    
    title1, title2 = "me1", "me2"
    cv2.imshow(title1, image)
    cv2.imshow(title2, image)
    
    cv2.setMouseCallback(title1, onMouse)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    2.3. 트렉바 이벤트

    • cv2.createTrackvar(trackbarname, winname, value, count, onCnage) : 트랙바를 생성 후 지정한 윈도우에 추가

      • value : 트랙바 슬라이더의 위치를 반영하는 값(정수)

      • count : 트랙바 슬라이더의 최댓값, 최솟값은 항상 0이다.

      • onCnage : 트랙바 슬라이더의 값이 변경될 때 호출되는 콜백 함수

    • onCnage(pos) : 트랙바 슬라이더의 위치가 변경될 때마다 호출되는 콜백 함수

      • pos : 트랙바 슬라이더 위치

    • cv2.getTrackbarPos(trackbarname, winname) : 지정한 트랙바의 슬라이더 위치를 반환

    • cv2.setTrackbarPos(trackbarname, winname, pos) : 지정한 트랙바의 슬라이더 위치를 설정

    import numpy as np
    import cv2
    
    def onChange(value):
        global image, title
        
        add_value = value - int(image[0][0])
        print("추가 화소값 : ", add_value)
        image[:] = image+add_value
        cv2.imshow(title, image)
    
    image = np.zeros((300, 500), np.uint8)
    title = "track"
    cv2.imshow(title, image)
    
    cv2.createTrackbar("bright", title, image[0][0], 255, onChange)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    3. 그리기 함수

    3.1. 직선 및 사각형 그리기

    • cv2.line(img, pt1, pt2, color [, thickness [, lineType[, shift]]]) : pt1에서 pt2를 잇는 직선을 그림

      • img : 그릴 대상 행렬(영상)

      • pt1, pt2 : 시작 좌표와 종료 좌표(정수형 튜플)

      • thickness : 선의 두께, cv2.FILLED일 경우 지정된 색으로 내부를 채움

      • color : 선의 색상(정수형 튜플)

      • lineType : 선의 형태

      • shift : 입력 좌표(pt1, pt2)에 대해 오른쪽으로 비트 시프트 연산한 결과를 좌표로 지정해서 직선을 그림

    • cv2.rectangle(img, pt1, pt2, color [, thickness [, lineType [, shift]]])

    • cv2.rectangle(img, rec, color [, thickness [, lineType [, shift]]])

      • 사각형은 2가지 방식으로 그릴 수 있다.

        • pt1, pt2 : 시작 좌표와 종료 좌표(정수형), 왼쪽 위 모서리 좌표와 오른쪽 밑 모서리 좌표

        • rec : 사각형 영역(x, y, w, h)을 나타내는 4원소 튜플(정수형)

    import numpy as np
    import cv2
    
    blue, green, red = (255, 0, 0), (0, 255, 0), (0, 0, 255)
    image = np.zeros((400, 600, 3), np.uint8)
    image[:] = (255, 255, 255)
    
    pt1, pt2 = (50, 50), (250, 150)
    pt3, pt4 = (400, 150), (500, 50)
    roi = (50, 200, 200, 100) #reason of interesting 관심 영역? 내가 처리하고자 하는 영역. 보토 이렇게 표기함
    
    cv2.line(image, pt1, pt2, red)
    cv2.line(image, pt3, pt4, green, 3, cv2.LINE_AA)
    
    cv2.rectangle(image, pt1, pt2, blue, 3, cv2.LINE_4)
    cv2.rectangle(image, roi, red, 3, cv2.LINE_8)
    cv2.rectangle(image, (400, 200, 100, 100), green, cv2.FILLED)
    
    cv2.imshow("l&r", image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    3.2. 글자 쓰기

    • cv2.putText(img, text, org, fontFace, fontScale, color [, thickness [, lineType [, bottomLeftOrigin]]])

      • img : 문자열을 작성할 대상 행렬(영상)

      • text : 작성할 문자열

      • org : 문자열의 시작 좌표, 문자열에서 가장 왼쪽 하단을 의미

      • fontFace : 문자열의 폰트

      • fontScale : 글자 크기 확대 비율

      • color : 글자의 색상

      • thickness : 글자의 굵기

      • lineType : 글자 선의 형태

      • bottomLeftOrigin : 영상의 원점 좌표 설정(True-좌하단 왼쪽, False-좌상단)

    3.3. 원 그리기

    • cv2.circle(img, center, radius, color [, thickness [, lineType [, shift]]]) : center를 중심으로 radius 반지름의 원을 그린다.

      • img : 원을 그릴 대상 행렬

      • center : 원의 중심 좌표

      • radius : 원의 반지름

    3.4. 타원 그리기

    • cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color [, thickness [, lineType [, shift]]]) : center를 중심으로 axes크기의 타원을 그린다.

      • img : 그릴 대상 행렬

      • center : 원의 중심 좌표

      • axes : 타원의 절반 크기(x축 반지름, y축 반지름)

      • angle : 타원의 각도 (3시 방향이 0, 시계방향으로 회전)

      • startAngle : 호의 시작 각도

      • endAngle : 호의 종료 각도







    - 컬렉션 아티클