## 一、均值偏移

meanshift 背后的思想很简单。 考虑有一组点。 （它可以是像直方图反投影这样的像素分布）。 您有一个小窗口（可能是一个圆圈），您必须将该窗口移动到最大像素密度（或最大点数）的区域。 如下图所示：

### 1. OpenCV中的均值偏移

import numpy as np
import cv2 as cv
import argparse
# parser = argparse.ArgumentParser(description='This sample demonstrates the meanshift algorithm. \
#                                               https://www.bogotobogo.com/python/OpenCV_Python/images/mean_shift_tracking/slow_traffic_small.mp4')
# parser.add_argument('image',type=str, help='path to image file')
# args = parser.parse_args(args = [])
# cap = cv.VideoCapture(args.image)
cap = cv.VideoCapture('slow_traffic_small.mp4')
# take first frame of the video
# setup initial location of window
x, y, w, h = 300, 200, 100, 50 # simply hardcoded the values
track_window = (x, y, w, h)
# set up the ROI for tracking
roi = frame[y:y+h, x:x+w]
hsv_roi =  cv.cvtColor(roi, cv.COLOR_BGR2HSV)
mask = cv.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
cv.normalize(roi_hist,roi_hist,0,255,cv.NORM_MINMAX)
# Setup the termination criteria, either 10 iteration or move by at least 1 pt
term_crit = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1 )
while(1):
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_window = cv.meanShift(dst, track_window, term_crit)
# Draw it on image
x,y,w,h = track_window
img2 = cv.rectangle(frame, (x,y), (x+w,y+h), 255,2)
cv.imshow('img2',img2)
k = cv.waitKey(30) & 0xff
if k == 27:
break
else:
break

cap.release()
cv.destroyAllWindows()

## 二、凸轮偏移

s

=

2

M

00

256

s = 2 * \sqrt{\frac{M_{00}}{256}}
2 5 6 M 0 0 ​ ​ ​ 。 它还计算最佳拟合椭圆的方向。 它再次使用新的缩放搜索窗口和先前的窗口位置应用均值偏移。 该过程继续进行，直到满足所需的精度。

### 1. OpenCV中的凸轮偏移

import numpy as np
import cv2 as cv
import argparse
# parser = argparse.ArgumentParser(description='This sample demonstrates the camshift algorithm. \
#                                               https://www.bogotobogo.com/python/OpenCV_Python/images/mean_shift_tracking/slow_traffic_small.mp4')
# parser.add_argument('image', type=str, help='path to image file')
# args = parser.parse_args()
# cap = cv.VideoCapture(args.image)
cap = cv.VideoCapture('slow_traffic_small.mp4')
# take first frame of the video
# setup initial location of window
x, y, w, h = 300, 200, 100, 50 # simply hardcoded the values
track_window = (x, y, w, h)
# set up the ROI for tracking
roi = frame[y:y+h, x:x+w]
hsv_roi =  cv.cvtColor(roi, cv.COLOR_BGR2HSV)
mask = cv.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
cv.normalize(roi_hist,roi_hist,0,255,cv.NORM_MINMAX)
# Setup the termination criteria, either 10 iteration or move by at least 1 pt
term_crit = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1 )
while(1):
if ret == True:
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
dst = cv.calcBackProject([hsv],[0],roi_hist,[0,180],1)
# apply camshift to get the new location
ret, track_window = cv.CamShift(dst, track_window, term_crit)
# Draw it on image
pts = cv.boxPoints(ret)
pts = np.int0(pts)
img2 = cv.polylines(frame,[pts],True, 255,2)
cv.imshow('img2',img2)
k = cv.waitKey(30) & 0xff
if k == 27:
break
else:
break

cap.release()
cv.destroyAllWindows()

## 三、补充资料

1. French Wikipedia page on Camshift. (The two animations are taken from there)

1. Bradski, G.R., “Real time face and object tracking as a component of a perceptual user interface,” Applications of Computer Vision, 1998. WACV ’98. Proceedings., Fourth IEEE Workshop on , vol., no., pp.214,219, 19-21 Oct 1998

## 四、练习

#!/usr/bin/env python
'''
Camshift tracker
================
This is a demo that shows mean-shift based tracking
You select a color objects such as your face and it tracks it.
This reads from video camera (0 by default, or the camera number the user enters)
[1] http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.14.7673
Usage:
------
camshift.py [<video source>]
To initialize tracking, select the object with mouse
Keys:
-----
ESC   - exit
b     - toggle back-projected probability visualization
'''
# Python 2/3 compatibility
from __future__ import print_function
import sys
PY3 = sys.version_info[0] == 3
if PY3:
xrange = range
import numpy as np
import cv2 as cv
# local module
# 需要将video.py模块放置在同目录下进行引用
import video
from video import presets
class App(object):
def __init__(self, video_src):
self.cam = video.create_capture(video_src, presets['cube'])
cv.namedWindow('camshift')
cv.setMouseCallback('camshift', self.onmouse)
self.selection = None
self.drag_start = None
self.show_backproj = False
self.track_window = None
def onmouse(self, event, x, y, flags, param):
if event == cv.EVENT_LBUTTONDOWN:
self.drag_start = (x, y)
self.track_window = None
if self.drag_start:
xmin = min(x, self.drag_start[0])
ymin = min(y, self.drag_start[1])
xmax = max(x, self.drag_start[0])
ymax = max(y, self.drag_start[1])
self.selection = (xmin, ymin, xmax, ymax)
if event == cv.EVENT_LBUTTONUP:
self.drag_start = None
self.track_window = (xmin, ymin, xmax - xmin, ymax - ymin)
def show_hist(self):
bin_count = self.hist.shape[0]
bin_w = 24
img = np.zeros((256, bin_count*bin_w, 3), np.uint8)
for i in xrange(bin_count):
h = int(self.hist[i])
cv.rectangle(img, (i*bin_w+2, 255), ((i+1)*bin_w-2, 255-h), (int(180.0*i/bin_count), 255, 255), -1)
img = cv.cvtColor(img, cv.COLOR_HSV2BGR)
cv.imshow('hist', img)
def run(self):
while True:
if not _ret:
break
vis = self.frame.copy()
hsv = cv.cvtColor(self.frame, cv.COLOR_BGR2HSV)
mask = cv.inRange(hsv, np.array((0., 60., 32.)), np.array((180., 255., 255.)))
if self.selection:
x0, y0, x1, y1 = self.selection
hsv_roi = hsv[y0:y1, x0:x1]
hist = cv.calcHist( [hsv_roi], [0], mask_roi, [16], [0, 180] )
cv.normalize(hist, hist, 0, 255, cv.NORM_MINMAX)
self.hist = hist.reshape(-1)
self.show_hist()
vis_roi = vis[y0:y1, x0:x1]
cv.bitwise_not(vis_roi, vis_roi)
if self.track_window and self.track_window[2] > 0 and self.track_window[3] > 0:
self.selection = None
prob = cv.calcBackProject([hsv], [0], self.hist, [0, 180], 1)
term_crit = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1 )
track_box, self.track_window = cv.CamShift(prob, self.track_window, term_crit)
if self.show_backproj:
vis[:] = prob[...,np.newaxis]
try:
cv.ellipse(vis, track_box, (0, 0, 255), 2)
except:
print(track_box)
cv.imshow('camshift', vis)
ch = cv.waitKey(10)
if ch == 27:
break
if ch == ord('b'):
self.show_backproj = not self.show_backproj
cv.destroyAllWindows()
if __name__ == '__main__':
print(__doc__)
import sys
try:
#         video_src = sys.argv[1]
video_src = 'slow_traffic_small.mp4'

except:
video_src = 0
App(video_src).run()

Camshift tracker
================
This is a demo that shows mean-shift based tracking
You select a color objects such as your face and it tracks it.
This reads from video camera (0 by default, or the camera number the user enters)
[1] http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.14.7673
Usage:
------
camshift.py [<video source>]
To initialize tracking, select the object with mouse
Keys:
-----
ESC   - exit
b     - toggle back-projected probability visualization