Object Tracking이 구현된 파이썬 코드 공부하기

이양규·2022년 3월 16일
0
post-thumbnail

전체 코드

코드 출처 : 파이썬으로 만드는 OpenCV 프로젝트(이세우 저)

import cv2

trackers = [cv2.TrackerBoosting_create,
            cv2.TrackerMIL_create,
            cv2.TrackerKCF_create,
            cv2.TrackerTLD_create,
            cv2.TrackerMedianFlow_create,
            cv2.TrackerGOTURN_create, 
            cv2.TrackerCSRT_create,
            cv2.TrackerMOSSE_create]

trackerIdx = 0  
tracker = None
isFirst = True

video_src = 0 
video_src = "./soccer.mp4"

cap = cv2.VideoCapture(video_src)

fps = cap.get(cv2.CAP_PROP_FPS)
delay = int(1000/fps)
win_name = 'Tracking APIs'

while cap.isOpened():
    ret, frame = cap.read()
    
    # (+추가) 동영상 크기 조정을 위한 코드
    frame=cv2.resize(frame, dsize=None, fx=0.5, fy=0.5)
    
    if not ret:
        print('Cannot read video file')
        break
    
    img_draw = frame.copy()
    
    if tracker is None: 
        cv2.putText(img_draw, "Press the Space to set ROI!!", \
            (100,80), cv2.FONT_HERSHEY_SIMPLEX, 0.75,(0,0,255),2,cv2.LINE_AA)
    else:
        ok, bbox = tracker.update(frame)   
        (x,y,w,h) = bbox
        if ok: # 추적 성공
            cv2.rectangle(img_draw, (int(x), int(y)), (int(x + w), int(y + h)), \
                          (0,255,0), 2, 1)
        else : # 추적 실패
            cv2.putText(img_draw, "Tracking fail.", (100,80), \
                        cv2.FONT_HERSHEY_SIMPLEX, 0.75,(0,0,255),2,cv2.LINE_AA)
                
    trackerName = tracker.__class__.__name__
    
    cv2.putText(img_draw, str(trackerIdx) + ":"+trackerName , (100,20), \
                 cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0,255,0),2,cv2.LINE_AA)


    cv2.imshow(win_name, img_draw)
    
    key = cv2.waitKey(delay) & 0xff

    if key == ord(' ') or (video_src != 0 and isFirst): 
        isFirst = False
        roi = cv2.selectROI(win_name, frame, False) 
        if roi[2] and roi[3]:    
            tracker = trackers[trackerIdx]()   
            isInit = tracker.init(frame, roi)
    elif key in range(48, 56): 
        trackerIdx = key-48    
        if bbox is not None:
            tracker = trackers[trackerIdx]() 
            isInit = tracker.init(frame, bbox) 
    elif key == 27 : 
        break
    
else:
    print( "Could not open video")
cap.release()
cv2.destroyAllWindows()

코드 실행

Object Tracking??

시간이 지남에 따라 움직이는 물체를 찾는 과정

OpenCV??

실시간 컴퓨터 비전을 목적으로 한 프로그래밍 라이브러리

컴퓨터비전??

기계의 시각에 해당하는 부분을 연구하는 컴퓨터 과학의 최신 연구 분야 중 하나


💻 OpenCV 패키지 선언

import cv2

💻 트래커 객체 생성자 리스트 선언

trackers = [cv2.TrackerBoosting_create,
            cv2.TrackerMIL_create,
            cv2.TrackerKCF_create,
            cv2.TrackerTLD_create,
            cv2.TrackerMedianFlow_create,
            cv2.TrackerGOTURN_create, 
            cv2.TrackerCSRT_create,
            cv2.TrackerMOSSE_create]
  • cv.TrackerBoosing_create()
    AdaBoost 알고리즘 기반
    참고자료

  • cv2.TrackerMIL_create()
    MIL(Multiple Instance Learning) 알고리즘 기반
    참고자료

  • cv2.TrackerKCF_create()
    KCF(Kernelized Correlation Filters) 알고리즘 기반

  • cv2.TrackerTLD_create()
    TLD(Tracking, Learning and Detection) 알고리즘 기반
    참고자료

  • cv2.TrackerMedianFlow_create()
    객체의 전방향/역방향을 추적해서 불일치성을 측정

  • cv2.TrackerGOTURN_create()
    CNN(Convolutional Neural Networks) 기반
    참고자료

  • cv2.TrackerCSRT_create()
    CSRT(Channel and Spatial Reliability)

  • cv2.TrackerMOSSE_create()
    내부적으로 그레이 스케일 사용

💻 카메라, 동영상 선택

video_src = 0 # 첫 번째로 연결된 캠과 연결됨
video_src = "./soccer.mp4" # 동영상과 연결됨
  • 트래킹 대상에 따라 적절히 코드를 작성
  • 현재는 동영상에 트래킹을 적용하기 때문에 첫 번째 줄은 없어도 됨

💻 카메라(or 동영상) 열기

cap = cv2.VideoCapture(video_src)

💻 초당 프레임 수 구하기

fps = cap.get(cv2.CAP_PROP_FPS)

💻 딜레이 계산

delay = int(1000/fps)
  • 동영상을 적절한 속도로 재생하기 위해 딜레이를 구함

💻 프레임 읽기

ret, frame = cap.read()
  • 재생되는 비디오의 한 프레임씩 읽음
  • 프레임을 제대로 읽으면 ret 값은 True, 아니면 False

💻 관심영역 설정하기

img_draw = frame.copy()

📷 트래커가 생성되지 않았을 때

if tracker is None: 
    cv2.putText(img_draw, "Press the Space to set ROI!!", \
        (100,80), cv2.FONT_HERSHEY_SIMPLEX, 0.75,(0,0,255),2,cv2.LINE_AA)

📷 트래커가 생성되었을 때

else:
    ok, bbox = tracker.update(frame)   
    (x,y,w,h) = bbox
    if ok: # 추적 성공
        cv2.rectangle(img_draw, (int(x), int(y)), (int(x + w), int(y + h)), 
        \(0,255,0), 2, 1)
    else : # 추적 실패
        cv2.putText(img_draw, "Tracking fail.", (100,80), \
                    cv2.FONT_HERSHEY_SIMPLEX, 0.75 (0,0,255),2,cv2.LINE_AA)
  • 새로운 프레임에서 추적 위치를 찾는 코드
ok, bbox = tracker.update(frame) 
  • 추적 위치를 찾았다면 드래그 된 곳을 추적 공간으로 지정 (직사각형)
cv2.rectangle(img_draw, (int(x), int(y)), (int(x + w), int(y + h)),
  \(0,255,0), 2, 1)

💻 어떤 트래커가 사용 되었는지 알려주기

trackerName = tracker.__class__.__name__
    
cv2.putText(img_draw, str(trackerIdx) + ":"+trackerName , (100,20), \
                 cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0,255,0),2,cv2.LINE_AA)

💻 윈도우에 보여주기

cv2.imshow(win_name, img_draw)
  • img_draw
    : 트래커가 추적하는 부분 (직사각형)

💻 키보드 이벤트 처리

⚡ 키보드 입력 대기

key = cv2.waitKey(delay) & 0xff
  • delay 만큼 프로그램을 멈추고 있다가 키보드의 눌린 키에 대응하는 값을 반환

💡 스페이스 바 또는 비디오 파일 최초 실행

if key == ord(' ') or (video_src != 0 and isFirst): 
    isFirst = False
    roi = cv2.selectROI(win_name, frame, False) 
    if roi[2] and roi[3]:    
        tracker = trackers[trackerIdx]()   
        isInit = tracker.init(frame, roi)
  • 초기 객체의 위치 설정
roi = cv2.selectROI(win_name, frame, False)
  • 위치 설정 값이 있는 경우 트래커 객체 생성
 if roi[2] and roi[3]:    
     tracker = trackers[trackerIdx]()   
     isInit = tracker.init(frame, roi)
  • 객체를 초기화 하는 부분
isInit = tracker.init(frame, roi)

💡 스페이스 바 또는 비디오 파일 최초 실행이 아닐 경우

elif key in range(48, 56): 
    trackerIdx = key-48    
    if bbox is not None:
        tracker = trackers[trackerIdx]() 
        isInit = tracker.init(frame, bbox) 
  • 키보드 숫자 키 참고
    출처
  • 선택한 숫자로 트래커 인덱스 설정
trackerIdx = key-48 
  • 선택한 숫자의 트랙커 객체 생성
tracker = trackers[trackerIdx]() 

💡 종료 (나가기)

elif key == 27 : 
    break

💻 오픈한 객체 해제하기

cap.release()
cv2.destroyAllWindows()

0개의 댓글