Update to 2.0.0 tree from current Fremantle build
[opencv] / samples / swig_python / lkdemo.py
1 #! /usr/bin/env python
2
3 print "OpenCV Python version of lkdemo"
4
5 import sys
6
7 # import the necessary things for OpenCV
8 from opencv import cv
9 from opencv import highgui
10
11 #############################################################################
12 # some "constants"
13
14 win_size = 10
15 MAX_COUNT = 500
16
17 #############################################################################
18 # some "global" variables
19
20 image = None
21 pt = None
22 add_remove_pt = False
23 flags = 0
24 night_mode = False
25 need_to_init = False
26 # the default parameters
27 quality = 0.01
28 min_distance = 10
29
30 #############################################################################
31 # the mouse callback
32
33 # the callback on the trackbar
34 def on_mouse (event, x, y, flags, param):
35
36     # we will use the global pt and add_remove_pt
37     global pt
38     global add_remove_pt
39     
40     if image is None:
41         # not initialized, so skip
42         return
43
44     if event == highgui.CV_EVENT_LBUTTONDOWN:
45         # user has click, so memorize it
46         pt = cv.cvPoint (x, y)
47         add_remove_pt = True
48
49 #############################################################################
50 # so, here is the main part of the program
51
52 if __name__ == '__main__':
53
54     try:
55         # try to get the device number from the command line
56         device = int (sys.argv [1])
57
58         # got it ! so remove it from the arguments
59         del sys.argv [1]
60     except (IndexError, ValueError):
61         # no device number on the command line, assume we want the 1st device
62         device = 0
63
64     if len (sys.argv) == 1:
65         # no argument on the command line, try to use the camera
66         capture = highgui.cvCreateCameraCapture (device)
67
68     else:
69         # we have an argument on the command line,
70         # we can assume this is a file name, so open it
71         capture = highgui.cvCreateFileCapture (sys.argv [1])            
72
73     # check that capture device is OK
74     if not capture:
75         print "Error opening capture device"
76         sys.exit (1)
77         
78     # display a small howto use it
79     print "Hot keys: \n" \
80           "\tESC - quit the program\n" \
81           "\tr - auto-initialize tracking\n" \
82           "\tc - delete all the points\n" \
83           "\tn - switch the \"night\" mode on/off\n" \
84           "To add/remove a feature point click it\n"
85
86     # first, create the necessary windows
87     highgui.cvNamedWindow ('LkDemo', highgui.CV_WINDOW_AUTOSIZE)
88
89     # register the mouse callback
90     highgui.cvSetMouseCallback ('LkDemo', on_mouse, None)
91
92     while 1:
93         # do forever
94
95         # 1. capture the current image
96         frame = highgui.cvQueryFrame (capture)
97         if frame is None:
98             # no image captured... end the processing
99             break
100
101         if image is None:
102             # create the images we need
103             image = cv.cvCreateImage (cv.cvGetSize (frame), 8, 3)
104             grey = cv.cvCreateImage (cv.cvGetSize (frame), 8, 1)
105             prev_grey = cv.cvCreateImage (cv.cvGetSize (frame), 8, 1)
106             pyramid = cv.cvCreateImage (cv.cvGetSize (frame), 8, 1)
107             prev_pyramid = cv.cvCreateImage (cv.cvGetSize (frame), 8, 1)
108             eig = cv.cvCreateImage (cv.cvGetSize (frame), cv.IPL_DEPTH_32F, 1)
109             temp = cv.cvCreateImage (cv.cvGetSize (frame), cv.IPL_DEPTH_32F, 1)
110             points = [[], []]
111
112         # copy the frame, so we can draw on it
113         cv.cvCopy (frame, image)
114
115         # create a grey version of the image
116         cv.cvCvtColor (image, grey, cv.CV_BGR2GRAY)
117
118         if night_mode:
119             # night mode: only display the points
120             cv.cvSetZero (image)
121
122         if need_to_init:
123             # we want to search all the good points
124             # create the wanted images
125             
126             # search the good points
127             points [1] = cv.cvGoodFeaturesToTrack (
128                 grey, eig, temp,
129                 MAX_COUNT,
130                 quality, min_distance, None, 3, 0, 0.04)
131             
132             # refine the corner locations
133             cv.cvFindCornerSubPix (
134                 grey,
135                 points [1],
136                 cv.cvSize (win_size, win_size), cv.cvSize (-1, -1),
137                 cv.cvTermCriteria (cv.CV_TERMCRIT_ITER | cv.CV_TERMCRIT_EPS,
138                                    20, 0.03))
139                                                
140         elif len (points [0]) > 0:
141             # we have points, so display them
142
143             # calculate the optical flow
144             [points [1], status], something = cv.cvCalcOpticalFlowPyrLK (
145                 prev_grey, grey, prev_pyramid, pyramid,
146                 points [0], len (points [0]),
147                 (win_size, win_size), 3,
148                 len (points [0]),
149                 None,
150                 cv.cvTermCriteria (cv.CV_TERMCRIT_ITER|cv.CV_TERMCRIT_EPS,
151                                    20, 0.03),
152                 flags)
153             
154             # initializations
155             point_counter = -1
156             new_points = []
157             
158             for the_point in points [1]:
159                 # go trough all the points
160
161                 # increment the counter
162                 point_counter += 1
163                 
164                 if add_remove_pt:
165                     # we have a point to add, so see if it is close to
166                     # another one. If yes, don't use it
167                     dx = pt.x - the_point.x
168                     dy = pt.y - the_point.y
169                     if dx * dx + dy * dy <= 25:
170                         # too close
171                         add_remove_pt = 0
172                         continue
173
174                 if not status [point_counter]:
175                     # we will disable this point
176                     continue
177
178                 # this point is a correct point
179                 new_points.append (the_point)
180
181                 # draw the current point
182                 cv.cvCircle (image,
183                              cv.cvPointFrom32f(the_point),
184                              3, cv.cvScalar (0, 255, 0, 0),
185                              -1, 8, 0)
186
187             # set back the points we keep
188             points [1] = new_points
189             
190         if add_remove_pt:
191             # we want to add a point
192             points [1].append (cv.cvPointTo32f (pt))
193
194             # refine the corner locations
195             points [1][-1] = cv.cvFindCornerSubPix (
196                 grey,
197                 [points [1][-1]],
198                 cv.cvSize (win_size, win_size), cv.cvSize (-1, -1),
199                 cv.cvTermCriteria (cv.CV_TERMCRIT_ITER | cv.CV_TERMCRIT_EPS,
200                                    20, 0.03))[0]
201
202             # we are no more in "add_remove_pt" mode
203             add_remove_pt = False
204
205         # swapping
206         prev_grey, grey = grey, prev_grey
207         prev_pyramid, pyramid = pyramid, prev_pyramid
208         points [0], points [1] = points [1], points [0]
209         need_to_init = False
210         
211         # we can now display the image
212         highgui.cvShowImage ('LkDemo', image)
213
214         # handle events
215         c = highgui.cvWaitKey (10)
216
217         if c == '\x1b':
218             # user has press the ESC key, so exit
219             break
220
221         # processing depending on the character
222         if c in ['r', 'R']:
223             need_to_init = True
224         elif c in ['c', 'C']:
225             points = [[], []]
226         elif c in ['n', 'N']:
227             night_mode = not night_mode