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