camshift.py 3.97 KB
Newer Older
1 2 3 4 5 6 7
'''
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)
8

9
http://www.robinhewitt.com/research/track/camshift.html
10

11 12 13
Usage:
------
    camshift.py [<video source>]
14

15 16
    To initialize tracking, select the object with mouse
  
17
Keys:
18 19 20
-----
    ESC   - exit
    b     - toggle back-projected probability visualization
21
'''
22

23 24 25 26
import numpy as np
import cv2
import video

27 28 29 30 31 32 33 34 35 36 37

class App(object):
    def __init__(self, video_src):
        self.cam = video.create_capture(video_src)
        ret, self.frame = self.cam.read()
        cv2.namedWindow('camshift')
        cv2.setMouseCallback('camshift', self.onmouse)

        self.selection = None
        self.drag_start = None
        self.tracking_state = 0
38
        self.show_backproj = False
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71

    def onmouse(self, event, x, y, flags, param):
        x, y = np.int16([x, y]) # BUG
        if event == cv2.EVENT_LBUTTONDOWN:
            self.drag_start = (x, y)
            self.tracking_state = 0
        if self.drag_start: 
            if flags & cv2.EVENT_FLAG_LBUTTON:
                h, w = self.frame.shape[:2]
                xo, yo = self.drag_start
                x0, y0 = np.maximum(0, np.minimum([xo, yo], [x, y]))
                x1, y1 = np.minimum([w, h], np.maximum([xo, yo], [x, y]))
                self.selection = None
                if x1-x0 > 0 and y1-y0 > 0:
                    self.selection = (x0, y0, x1, y1)
            else:
                self.drag_start = None
                if self.selection is not None:
                    self.tracking_state = 1

    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])
            cv2.rectangle(img, (i*bin_w+2, 255), ((i+1)*bin_w-2, 255-h), (int(180.0*i/bin_count), 255, 255), -1)
        img = cv2.cvtColor(img, cv2.COLOR_HSV2BGR)
        cv2.imshow('hist', img)

    def run(self):
        while True:
            ret, self.frame = self.cam.read()
72
            vis = self.frame.copy()
73
            hsv = cv2.cvtColor(self.frame, cv2.COLOR_BGR2HSV)
74
            mask = cv2.inRange(hsv, np.array((0., 60., 32.)), np.array((180., 255., 255.)))
75 76 77

            if self.selection:
                x0, y0, x1, y1 = self.selection
78
                self.track_window = (x0, y0, x1-x0, y1-y0)
79
                hsv_roi = hsv[y0:y1, x0:x1]
80 81
                mask_roi = mask[y0:y1, x0:x1]
                hist = cv2.calcHist( [hsv_roi], [0], mask_roi, [16], [0, 180] )
82 83 84 85
                cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX);
                self.hist = hist.reshape(-1)
                self.show_hist()
                
86 87 88
                vis_roi = vis[y0:y1, x0:x1]
                cv2.bitwise_not(vis_roi, vis_roi)
                vis[mask == 0] = 0
89 90 91 92

            if self.tracking_state == 1:
                self.selection = None
                prob = cv2.calcBackProject([hsv], [0], self.hist, [0, 180], 1)
93
                prob &= mask
94
                term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 )
95
                track_box, self.track_window = cv2.CamShift(prob, self.track_window, term_crit)
96
                
97 98 99 100
                if self.show_backproj:
                    vis[:] = prob[...,np.newaxis]
                try: cv2.ellipse(vis, track_box, (0, 0, 255), 2)
                except: print track_box
101
                
102 103 104 105
            cv2.imshow('camshift', vis)

            ch = cv2.waitKey(5)
            if ch == 27:
106
                break
107 108
            if ch == ord('b'):
                self.show_backproj = not self.show_backproj
109 110 111 112 113


if __name__ == '__main__':
    import sys
    try: video_src = sys.argv[1]
114
    except: video_src = 0
115
    print __doc__
116 117
    App(video_src).run()