Отслеживание и обнаружение объектов являются фундаментальными задачами компьютерного зрения. OpenCV предоставляет два популярных алгоритма для этих задач: MeanShift и CAMShift. MeanShift — это базовый алгоритм отслеживания, а CAMShift — это расширение MeanShift, которое хорошо работает с объектами разных размеров. Идея этого алгоритма состоит в том, чтобы переместить небольшое окно (набор пикселей объектов), чтобы получить пиксели высокой плотности, такие же, как при обратной проекции гистограммы.

вы можете обнаружить, что поток в целом один и тот же, за исключением нескольких одной или двух функций, но разница в результатах обоих алгоритмов очень ощутима…

Ход обоих алгоритмов таков:…

  1. Сначала настройте цель и найдите ее гистограмму для обратного проецирования цели.
  2. Также установите одно начальное местоположение
  3. Установите критерии завершения

Среднее смещение:….

import cv2

# Open a video capture object
cap = cv2.VideoCapture('video.mp4')

# Read the first frame
ret, frame = cap.read()

# Define a region of interest (ROI) for tracking
x, y, w, h = 300, 200, 100, 100
roi = frame[y:y+h, x:x+w]

# Convert the ROI to HSV color space
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)

# Calculate the histogram of the ROI
roi_hist = cv2.calcHist([hsv_roi], [0], None, [180], [0, 180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)

# Set the termination criteria for MeanShift
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

while True:
    ret, frame = cap.read()
    if not ret:
        break
    
    # Convert the frame to HSV color space
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    
    # Calculate the back projection using the histogram
    dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)
    
    # Apply MeanShift to get the new location of the object
    ret, track_window = cv2.meanShift(dst, (x, y, w, h), term_crit)
    
    # Draw the tracked window on the frame
    x, y, w, h = track_window
    cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
    
    # Display the result
    cv2.imshow('MeanShift Tracking', frame)
    
    if cv2.waitKey(30) & 0xFF == 27:  # Press 'Esc' to exit
        break

cap.release()
cv2.destroyAllWindows()

Другой фрагмент кода для того же алгоритма:…

import numpy as np
import cv2 as cv
cap = cv.VideoCapture('C:\\Users\\RANGER\\Desktop\\Computer_Vision_Opencv\\image data\\Roadside.mp4')

# take first frame of the video
ret, frame = cap.read()

# setup initial location of window 318,336,454,488
#577,469,667,686, 480,405,531,581
#x, y, width, height = 318, 454, 336,488 
x, y, width, height = 581,405,531,480
track = (x, y ,width, height)

# set up the ROI for tracking
roi = frame[y:y+height, x : x+width] # passing an individual object location in video . 
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV) # we need histogram below so we need to convert ROI to HSV.

mask = cv.inRange(hsv_roi, np.array((0., 60., 32.)), np.array((180., 255., 255))) # those array are specific array which will define threshold.
roi_hist = cv.calcHist([hsv_roi], [0], mask, [180], [0, 180]) # creating histogram after masking.
cv.normalize(roi_hist, roi_hist, 0, 255,cv.NORM_MINMAX)

# Setup the termination criteria, either 10 iteration or move by atleast 1 pt
termntn = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1)
cv.imshow('roi',roi)
while  True:
    ret, frame = cap.read()
    
    if ret == True:

        hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
        dst = cv.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)
        
        # apply meanshift to get the new location
        ret, track = cv.meanShift(dst, track, termntn)
        
        # Draw it on image
        x,y,w,h = track
        final = cv.rectangle(frame, (x,y), (x+w, y+h), (0,0,255), 3)

        #cv.imshow('dst', dst)
        frame = cv.resize(final,(600,600))
        cv.imshow('final_image',frame)
        k = cv.waitKey(30) & 0xff
        if k == 27:
            break
    else:
        break
cv.destroyAllWindows()

Выход:…

Недостатки этого алгоритма в том, что

  • Фиксированное целевое окно не должно быть изменено
  • Другой вариант — сохранить цель в списке или словаре, а затем использовать ее.
  • Но в любом случае придется делать вручную…

CAMshift:….

CAMShift расширяет MeanShift, адаптируя размер окна поиска в зависимости от изменений формы и размера объекта. Полная форма CAMshift — «Непрерывно адаптивный средний сдвиг».

import cv2

cap = cv2.VideoCapture('video.mp4')

ret, frame = cap.read()
x, y, w, h = 300, 200, 100, 100
track_window = (x, y, w, h)

roi = frame[y:y+h, x:x+w]
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
roi_hist = cv2.calcHist([hsv_roi], [0], None, [180], [0, 180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)

term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

while True:
    ret, frame = cap.read()
    if not ret:
        break
    
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)
    
    ret, track_window = cv2.CamShift(dst, track_window, term_crit)
    
    pts = cv2.boxPoints(ret)
    pts = np.int0(pts)
    img2 = cv2.polylines(frame, [pts], True, (0, 255, 0), 2)
    
    cv2.imshow('CAMShift Tracking', img2)
    
    if cv2.waitKey(30) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

Другой фрагмент кода для того же алгоритма:….

import numpy as np
import cv2 as cv
cap = cv.VideoCapture('C:\\Users\\RANGER\\Desktop\\Computer_Vision_Opencv\\image data\\Roadside.mp4')

# take first frame of the video
ret, frame = cap.read()

# setup initial location of window
#x, y, width, height = 580, 30, 80,150
x, y, width, height = 318, 454, 336,488
track = (x, y ,width, height)

# set up the ROI for tracking
roi = frame[y:y+height, x : x+width]
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
mask = cv.inRange(hsv_roi, np.array((0., 60., 32.)), np.array((180., 255., 255)))
roi_hist = cv.calcHist([hsv_roi], [0], mask, [180], [0, 180])
cv.normalize(roi_hist, roi_hist, 0, 255,cv.NORM_MINMAX)

# Setup the termination criteria, either 10 iteration or move by atleast 1 pt
termntn = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1)
cv.imshow('roi',roi)
while  True:
    ret, frame = cap.read()
    
    if ret == True:

        hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
        dst = cv.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)
        
        # apply meanshift to get the new location
        ret, track = cv.CamShift(dst, track, termntn)
        
        # Draw it on image
        #x,y,w,h = track
        #final = cv.rectangle(frame, (x,y), (x+w, y+h), (0,0,255), 3)
        
        #Try to draw rotating rectangle
        pts =cv.boxPoints(ret)
        pts = np.int64(pts)
        final = cv.polylines(frame,[pts],True,(255,0,0),2)
        
        
        
        
        
        
        cv.imshow('dst', dst)
        frame = cv.resize(final,(600,600))
        cv.imshow('final_image',frame)
        k = cv.waitKey(30) & 0xff
        if k == 27:
            break
    else:
        break
cv.destroyAllWindows()

Выход :…..

Замените 'video.mp4' на путь к вашему видеофайлу. В обоих примерах отслеживаемый объект будет показан с ограничивающей рамкой вокруг него. CAMShift обычно работает лучше при изменении размера объекта.

Для получения дополнительной информации об этих алгоритмах посетите https://docs.opencv.org/4.x/d7/d00/tutorial_meanshift.html.