DEV Community

thanas11065
thanas11065

Posted on

การ Object Tracking with Mean shift Algorithms using OpenCV

ถ้าเราต้องการ tracking วัตถุจาก video หนึ่งในวิธีที่เหมาะสมที่ใช้สำหรับการ tracking ข้อมูลแบบนี้ คือ การใช้ Mean shift Algorithms using OpenCV

บทความนี้ จะดูเกี่ยวกับ Object Tracking ใน Python โดยเราจะใช้ visual studio code ในการรันโค้ด โดย dataset ที่เราจะใช้เป็นตัวอย่างคือ example-video ซึ่งเป็นข้อมูล mp4 ได้มาจาก siromer จาก github
link:
https://github.com/siromermer/Object-Tracker-Meanshift-Camshift-Algorithm

ขั้นตอนที่ 1 นำเข้าข้อมูล

import cv2
import numpy as np 

"""
    How it works ? 
    when user run this script there is gonna be screen that displays first frame of video , by pressing mouse right  button user defines first point pair and after one more press to
    right button user defines second point , and there is gonna be rectangle created by this point 
    program tries to track this rectangle , if image inside of that rectangle is contains one color , program  runs more accurately 
    after defining rectangle press esc key and video will be shown to you
    there is 6 color option for now : red , orange,yellow,green,blue,violet
"""


# STEP 1 : User choices object with rectangle from first frame of video  , press mouse right button for first point pair and same button for second point pair

# path to video  
video_path="Hiphop.mp4"  # yellow.mp4 ve "plane.mp4" , helicopter.mp4
video = cv2.VideoCapture(video_path)

# read only first frame for drawing rectangle for desired object
ret,frame = video.read()

#  i am giving  big random numbers for x_min and y_min because if you initialize them as zeros whatever coordinate you go minimum will be zero 
x_min,y_min,x_max,y_max=36000,36000,0,0


# function for choosing min and max coordinates 
def coordinat_chooser(event,x,y,flags,param):
    global go , x_min , y_min, x_max , y_max

    # when you click right button it is gonna give variables some coordinates
    if event==cv2.EVENT_RBUTTONDOWN:

        # if current coordinate of x lower than the x_min it will be new x_min , same rules apply for y_min 
        x_min=min(x,x_min) 
        y_min=min(y,y_min)

         # if current coordinate of x higher than the x_max it will be new x_max , same rules apply for y_max
        x_max=max(x,x_max)
        y_max=max(y,y_max)

        # draw rectangle
        cv2.rectangle(frame,(x_min,y_min),(x_max,y_max),(0,255,0),1)


    """
        if you didnt like your rectangle (maybe if you did some misscliks) ,  reset coordinates with middle button of your mouse
        if you press middle button of your mouse coordinate will reset and you can give new 2 point pair for your rectangle
    """
    if event==cv2.EVENT_MBUTTONDOWN:
        print("reset coordinate  data")
        x_min,y_min,x_max,y_max=36000,36000,0,0


cv2.namedWindow('coordinate_screen')
# Set mouse handler for the specified window , in this case "coordinate_screen" window
cv2.setMouseCallback('coordinate_screen',coordinat_chooser)


while True:
    cv2.imshow("coordinate_screen",frame) # show only first frame 

    k = cv2.waitKey(5) & 0xFF # after drawing rectangle press esc   
    if k == 27:
        break
Enter fullscreen mode Exit fullscreen mode

ตัวอย่างผลที่ได้จาก code

Image description
เป็นการนำข้อมูลเข้ามาโดยจะสร้างเฟรมเพิ่มมา และ สร้างกรอบจากการกด คลิ๊กขวาเพื่อไปใช้คำนวนต่อ

ขั้นตอนที่ 2 หาสีภายในพื้นที่กรอบสี่เหลี่ยมอยู่

# STEP 2 : Program finds color of object that user choose  

# inside of rectangle that user draw 
object_image=frame[y_min:y_max,x_min:x_max,:]

hsv_object=cv2.cvtColor(object_image,cv2.COLOR_BGR2HSV)    

# cx and cy are center of rectangle that user choose 
height, width, _ = hsv_object.shape
cx = int(width / 2)
cy = int(height / 2)

# take center pixel to find out which color of rectangle
pixel_center = hsv_object[cy, cx]
hue_value = pixel_center[0] # axis 0 is hue values 

# from hue_value find color
color =str()
if hue_value < 5:
    color = "red"
elif hue_value < 22:
    color = "orange"
elif hue_value < 33:
    color = "yellow"
elif hue_value < 78:
    color = "green"
elif hue_value < 131:
    color = "blue"
elif hue_value < 170:
    color = "violet"
else:
    color = "red"


# hue dict 
hue_dict={ "red":[[[0, 100, 100]],[10, 255, 255]],
           "orange":[[10, 100, 100],[20, 255, 255]],
           "yellow":[[20, 100, 100],[30, 255, 255]],
           "green":[[50, 100, 100],[70, 255, 255]],
           "blue":[[110,50,50],[130,255,255]],
           "violet":[[140, 50, 50],[170, 255, 255]]}

# find upper and lower  bound of image's color
lower_bound , upper_bound = np.asarray(hue_dict[color][0]) , np.asarray(hue_dict[color][1]) # lower and upper bound sequentially

print(f"detected color : {color}" )
Enter fullscreen mode Exit fullscreen mode

เป็นการหาสีภายในกรอบสี่เหลี่ยม

ขั้นตอนที่ 3 Tracking object

# STEP 3 : Tracking  object 

# this time display all video  , not just first frame (in first part only first frame displayed in screen because user was choosing object by drawing rectangle)   
video=cv2.VideoCapture(video_path)

# we need first frame for creating roi(region of interest)
ret,cap = video.read()

# coordinates that user give with his mouse 
x=x_min
y=y_min
w=x_max-x_min
h=y_max-y_min

track_window = (x, y, w, h)

# set up the ROI for tracking
roi = cap[y:y+h, x:x+w]

hsv_roi =  cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)

# use lower_bound and upper_bound  inside of inRange function
mask = cv2.inRange(hsv_roi, lower_bound,upper_bound )
roi_hist = cv2.calcHist([hsv_roi],[0],mask,[180],[0,180])
cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX)

# Setup the termination criteria, either 10 iteration or move by at least 1 pt
term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 )

while True:

    ret, frame = video.read()

    cv2.putText(frame,f"detected color : {color}" , (25,25),cv2.FONT_HERSHEY_SIMPLEX ,1,(0,0,255),1)


    if ret == True:
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
        dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1)

        # apply meanshift to get the new location
        ret, track_window = cv2.meanShift(dst, track_window, term_crit)

        # Draw it on image
        x,y,w,h = track_window
        img2 = cv2.rectangle(frame, (x,y), (x+w,y+h), 255,2)
        cv2.imshow('img2',img2)

        k = cv2.waitKey(30) & 0xff
        if k == 27:
            break


Enter fullscreen mode Exit fullscreen mode

ตัวอย่างผลที่ได้จาก code

Image description
ส่วนนี้จะเป็นในส่วนของการติดตามวัตถุ
โดยโค้ดจะวนลูปทำงานจนกว่าผู้ใช้จะกดปุ่ม 'ESC' เพื่อออกจากโปรแกรม และในแต่ละเฟรมจะแสดงสีของวัตถุที่ติดตามได้ด้วยการแสดงข้อความบนเฟรม

สรุปผล
โดยโค้ดข้างต้นเป็นวาดกรอบสี่เหลี่ยมโดยนำค่าสีจากในกรอบสี่เหลี่ยม ในเฟรมแรกของ video โดยโปรแกรมจะพยายามติดตามสี่เหลี่ยมนี้ในวิดีโอ หากภาพภายในสี่เหลี่ยมนั้นมีเฉพาะสีเดียวกัน โปรแกรมจะทำงานได้แม่นยำมากขึ้น แต่ถ้าหากกรเคลื่อนไหวภายใน video เร็วเกินไปอาจทำให้เกิดคลาดเคลื่อนของการ tranking ได้

Top comments (0)