Move the sources to trunk
[opencv] / interfaces / matlab / toolbox / opencv / cvdemos / flowdemo.m
1 function flowdemo(action,varargin);\r
2 %   OpenCV Optical Flow functions demo\r
3 \r
4 global demoName;\r
5 demoName = 'OpenCV Optical Flow demo';\r
6 if nargin<1,\r
7    action='InitializeDEMO';\r
8 end;\r
9 \r
10 feval(action,varargin{:});\r
11 return;\r
12 \r
13 \r
14 %%%\r
15 %%%  Sub-function - InitializeDEMO\r
16 %%%\r
17 \r
18 function InitializeDEMO()\r
19 \r
20 global demoName;\r
21 \r
22 % If demo is already running, bring it to the foreground.\r
23 h = findobj(allchild(0), 'tag', demoName);\r
24 if ~isempty(h)\r
25    figure(h(1))\r
26    return\r
27 end\r
28 \r
29 screenD = get(0, 'ScreenDepth');\r
30 if screenD>8\r
31    grayres=256;\r
32 else\r
33    grayres=128;\r
34 end\r
35  \r
36 imgSize = [320, 240];\r
37 ctrHt = 19; % controls' height\r
38 \r
39 %==================================\r
40 % Set up the figure\r
41 DemoFig=figure( ...\r
42    'Name',demoName, ...\r
43    'NumberTitle','off', 'HandleVisibility', 'on', ...\r
44    'tag', demoName, ...\r
45    'Visible','off', 'Resize', 'off',...\r
46    'BusyAction','Queue','Interruptible','off',...\r
47    'IntegerHandle', 'off', ...\r
48    'Doublebuffer', 'on', ...\r
49    'Units', 'pixels', ...\r
50    'Colormap', gray(grayres));\r
51 \r
52 figpos = get(DemoFig, 'Position');\r
53 figpos(3) = 2.2*imgSize(1);\r
54 figpos(4) = imgSize(2) + 10*ctrHt;\r
55 set(DemoFig, 'Position', figpos);\r
56 \r
57 %==================================\r
58 % Set up the image axes\r
59 row = figpos(4); col = figpos(3);\r
60 vertSpac = ctrHt;\r
61 horSpac = (col-2*imgSize(1))/3;\r
62 hSrcAx = axes('Parent', DemoFig, ...\r
63    'units', 'pixels', ...\r
64    'BusyAction','Queue','Interruptible','off',...\r
65    'ydir', 'reverse', ...\r
66    'XLim', [.5 imgSize(1)+0.5], ...\r
67    'YLim', [.5 imgSize(2)+0.5],...\r
68    'CLim', [0 255], ...\r
69    'XTick',[],'YTick',[], ...\r
70    'Position', [horSpac row-vertSpac-imgSize(2) imgSize], ...\r
71    'UserData', []);\r
72 title('Source Image');\r
73 \r
74 hDstAx = axes('Parent', DemoFig, ...\r
75    'units', 'pixels', ...\r
76    'BusyAction','Queue','Interruptible','off',...\r
77    'ydir', 'reverse', ...\r
78    'XLim', [.5 imgSize(1)+0.5], ...\r
79    'YLim', [.5 imgSize(2)+0.5],...\r
80    'CLim', [0 255], ...\r
81    'XTick',[],'YTick',[], ...\r
82    'Position', [2 * horSpac + imgSize(1) row-vertSpac-imgSize(2) imgSize], ...\r
83    'UserData', []);\r
84 title('Destination Image');\r
85 \r
86 %==================================\r
87 % Set up the images\r
88 blank = repmat(uint8(0),imgSize(2),imgSize(1));\r
89 hSrcImage = image('Parent', hSrcAx,...\r
90    'CData', blank, ...\r
91    'BusyAction','Queue','Interruptible','off',...\r
92    'CDataMapping', 'scaled', ...\r
93    'Xdata', [1 1+imgSize(1)],...\r
94    'Ydata', [1 1+imgSize(2)],...\r
95    'ButtonDownFcn', 'flowdemo(''GetFeatures'')', ...\r
96    'EraseMode', 'none', ...\r
97    'UserData', []);\r
98 \r
99 hDstImage = image('Parent', hDstAx,...\r
100    'CData', blank, ...\r
101    'BusyAction','Queue','Interruptible','off',...\r
102    'CDataMapping', 'scaled', ...\r
103    'Xdata', [1 1+imgSize(1)],...\r
104    'Ydata', [1 1+imgSize(2)],...\r
105    'EraseMode', 'none', ...\r
106    'UserData', []);\r
107 \r
108 %====================================\r
109 % Information for all buttons (and menus)\r
110 btnWid=100;\r
111 btnHt=1.5*ctrHt;\r
112 \r
113 %====================================\r
114 % The CONSOLE frame\r
115 frmBorder=0.5 * ctrHt;\r
116 dstImgPos = get(hDstAx, 'Position');\r
117 \r
118 frmColor = [0.45, 0.45, 0.45];\r
119 \r
120 frmWidth  = 2*frmBorder + btnWid;\r
121 frmHeight = 3*frmBorder + 2*btnHt;\r
122 frmLeft   = dstImgPos(1);\r
123 frmBottom = dstImgPos(2)-ctrHt-frmHeight;\r
124 frmPos=[frmLeft, frmBottom, ...\r
125          frmWidth, frmHeight];\r
126 h=uicontrol( ...\r
127    'Parent', DemoFig, ...\r
128    'BusyAction','Queue','Interruptible','off',...\r
129    'Style','frame', ...\r
130    'Units','pixels', ...\r
131    'Position',frmPos, ...\r
132    'BackgroundColor', frmColor);\r
133 \r
134 %====================================\r
135 % The Apply button\r
136 labelStr='Apply';\r
137 callbackStr='flowdemo(''Apply'')';\r
138 yPos=frmBottom+frmBorder;\r
139 applyHndl=uicontrol( ...\r
140    'Parent', DemoFig, ...\r
141    'BusyAction','Queue','Interruptible','off',...\r
142    'Style','pushbutton', ...\r
143    'Units','pixels', ...\r
144    'Position',[frmLeft+frmBorder frmBottom+btnHt+2*frmBorder btnWid btnHt], ...\r
145    'String',labelStr, ...\r
146    'Enable', 'off', ...\r
147    'Callback',callbackStr);\r
148 \r
149 \r
150 %====================================\r
151 % The CLOSE button\r
152 labelStr='Close';\r
153 callbackStr='close(gcf)';\r
154 \r
155 closeHndl=uicontrol( ...\r
156    'Parent', DemoFig, ...\r
157    'BusyAction','Queue','Interruptible','off',...\r
158    'Style','pushbutton', ...\r
159    'Units','pixels', ...\r
160    'Position',[frmLeft+frmBorder frmBottom+frmBorder btnWid btnHt], ...\r
161    'Enable', 'off', ...\r
162    'String',labelStr, ...\r
163    'Callback',callbackStr);\r
164 \r
165 c = get(DemoFig,'Color');\r
166 \r
167 % Status bar\r
168 % rangePos = [64 3 280 15];\r
169 rangePos = [0 .01 1 .05];\r
170 hStatus = uicontrol( ...\r
171    'Parent', DemoFig, ...\r
172    'BusyAction','Queue','Interruptible','off',...\r
173    'Style','text', ...\r
174    'Units','normalized', ...\r
175    'Position',rangePos, ...\r
176    'Horiz','center', ...\r
177    'Background',c, ...\r
178    'Foreground',[.8 0 0], ...\r
179    'Tag', 'Status', ...\r
180    'String','Status bar');\r
181 \r
182 srcImgPos = get(hSrcAx, 'Position');\r
183 \r
184 %====================================\r
185 % The Good Features frame\r
186 \r
187 frmWidth  = 2*frmBorder + btnWid;\r
188 frmHeight = 3*frmBorder + 2*btnHt;\r
189 frmLeft   = srcImgPos(1)+srcImgPos(3)-frmWidth;\r
190 frmBottom = srcImgPos(2)-ctrHt-frmHeight;\r
191 frmPos=[frmLeft, frmBottom, ...\r
192          frmWidth, frmHeight];\r
193 h=uicontrol( ...\r
194    'Parent', DemoFig, ...\r
195    'BusyAction','Queue','Interruptible','off',...\r
196    'Style','frame', ...\r
197    'Units','pixels', ...\r
198    'Position',frmPos, ...\r
199    'Background', frmColor);\r
200 \r
201 \r
202 %====================================\r
203 % The Good Features Label\r
204 pos = [frmLeft+frmBorder, frmBottom + frmHeight - ctrHt-1, ...\r
205        frmWidth-2*frmBorder, ctrHt];\r
206 h = uicontrol( ...\r
207    'Parent', DemoFig, ...\r
208    'BusyAction','Queue','Interruptible','off',...\r
209    'Style','text', ...\r
210    'Units','pixels', ...\r
211    'Position',pos, ...\r
212    'Horiz','center', ...\r
213    'Background', frmColor, ...\r
214    'Foreground','black', ...\r
215    'String','Good Features');\r
216 \r
217 %====================================\r
218 % The Good Features Number Label\r
219 pos = [frmLeft+frmBorder, ...\r
220        frmBottom + frmHeight - 1*ctrHt-2*frmBorder, ...\r
221        (frmWidth-3*frmBorder)/2, ctrHt];\r
222 h = uicontrol( ...\r
223    'Parent', DemoFig, ...\r
224    'BusyAction','Queue','Interruptible','off',...\r
225    'Style','text', ...\r
226    'Units','pixels', ...\r
227    'Position',pos, ...\r
228    'Horiz','right', ...\r
229    'Background', frmColor, ...\r
230    'Foreground','black', ...\r
231    'String','Number: ');\r
232 \r
233 %====================================\r
234 % The Good Features Number Edit\r
235 pos = [frmLeft+2*frmBorder+(frmWidth-3*frmBorder)/2, ...\r
236        frmBottom + frmHeight - 1*ctrHt-2*frmBorder, ...\r
237        (frmWidth-3*frmBorder)/2, ctrHt];\r
238 hNumEdit=uicontrol( ...\r
239    'Parent', DemoFig, ...\r
240    'BusyAction','Queue','Interruptible','off',...\r
241    'Style','edit', ...\r
242    'Background','white', ...\r
243    'Foreground','black', ...\r
244    'Units','pixels', ...\r
245    'Position',pos, ...\r
246    'String','20', ...\r
247    'Horiz', 'right',...\r
248    'Tag','AppEdit', ...\r
249    'UserData', [20], ...\r
250    'Callback','flowdemo(''ControlsUpdate'')');\r
251 \r
252 %====================================\r
253 % The Generate button\r
254 labelStr='Generate';\r
255 callbackStr='flowdemo(''GoodFeatures'')';\r
256 \r
257 genHndl=uicontrol( ...\r
258    'Parent', DemoFig, ...\r
259    'BusyAction','Queue','Interruptible','off',...\r
260    'Style','pushbutton', ...\r
261    'Units','pixels', ...\r
262    'Position',[frmLeft+frmBorder frmBottom+frmBorder btnWid btnHt], ...\r
263    'Enable', 'off', ...\r
264    'String',labelStr, ...\r
265    'Callback',callbackStr);\r
266 \r
267 setstatus(DemoFig, 'Initializing Demo...');\r
268 set(DemoFig, 'Pointer', 'watch');\r
269 drawnow;\r
270 set(DemoFig, 'Visible','on');\r
271 \r
272 % Put handles to graphics objects and controls in the figure's userdata\r
273 handles.SrcImage = hSrcImage;\r
274 handles.DstImage = hDstImage;\r
275 \r
276 handles.SrcAx = hSrcAx;\r
277 handles.DstAx = hDstAx;\r
278 \r
279 handles.NumEdit = hNumEdit;\r
280 \r
281 set(DemoFig, 'UserData', handles);\r
282 \r
283 LoadNewImage(DemoFig);\r
284 \r
285 set(DemoFig, 'HandleVisibility','Callback')\r
286 set([closeHndl applyHndl genHndl], 'Enable', 'on');\r
287 return\r
288 \r
289 \r
290 %%%\r
291 %%%  Sub-Function - LoadNewImage\r
292 %%%\r
293 \r
294 function LoadNewImage(DemoFig)\r
295 \r
296 if nargin<1\r
297    DemoFig = gcbf;\r
298 end\r
299 \r
300 set(DemoFig,'Pointer','watch');\r
301 \r
302 handles = get(DemoFig,'UserData');\r
303 \r
304 hSrcImage = handles.SrcImage;\r
305 hDstImage = handles.DstImage;\r
306 \r
307 rock1 = [];\r
308 rock2 = [];\r
309 load cvdemos rock1 rock2;\r
310 \r
311 lkrock1 = [];\r
312 load cvdemos lkrock1;\r
313 \r
314 img = rock1;\r
315 featuresA = lkrock1(1:10:200,:);\r
316 set(hSrcImage, 'Cdata', img);\r
317 set(hSrcImage, 'UserData', featuresA);\r
318 \r
319 img = rock2;\r
320 set(hDstImage, 'Cdata', img);\r
321 set(hDstImage, 'UserData', []);\r
322 \r
323 drawnow;\r
324 \r
325 setstatus(DemoFig, 'Press ''Apply'' button');\r
326 Apply(DemoFig);\r
327 return;\r
328 \r
329 \r
330 %%%\r
331 %%%  Sub-Function - Apply\r
332 %%%\r
333 \r
334 function Apply(DemoFig)\r
335 \r
336 if nargin<1\r
337    DemoFig = gcbf;\r
338 end\r
339 \r
340 handles = get(DemoFig,'UserData');\r
341 \r
342 hSrcImage=handles.SrcImage;\r
343 hDstImage=handles.DstImage;\r
344 \r
345 set(DemoFig,'Pointer','watch');\r
346 setstatus(DemoFig, 'Calculating flow...'); drawnow;\r
347 \r
348 srcImage = get(hSrcImage, 'CData');\r
349 dstImage = get(hDstImage, 'CData');\r
350 \r
351 featuresA = get(hSrcImage, 'UserData');\r
352 \r
353 winSize = [10, 10];\r
354 level = 2;\r
355 criteria = [20, 0.03];\r
356 \r
357 %    [featuresA(:,2)-1, featuresA(:,1)-1], [featuresA(:,2)-1, featuresA(:,1)-1], ...\r
358 [featuresB, error] = cvCalcOpticalFlowPyrLK(srcImage, dstImage, ...\r
359     featuresA, featuresA, ...\r
360     winSize, level, criteria);\r
361 %featuresB = [featuresB(:,2), featuresB(:,1)]+1;\r
362 \r
363 set(hDstImage, 'UserData', featuresB);\r
364 FeaturesUpdate(DemoFig);\r
365 \r
366 setstatus(DemoFig, 'Done');\r
367 set(DemoFig,'Pointer','arrow'); drawnow\r
368 return\r
369 \r
370 \r
371 %%%\r
372 %%%  Sub-function - ControlsUpdate\r
373 %%%\r
374 \r
375 function ControlsUpdate(DemoFig)\r
376 \r
377 if nargin<1\r
378    DemoFig = gcbf;\r
379 end;\r
380 \r
381 handles = get(DemoFig,'UserData');\r
382 \r
383 hNumEdit = handles.NumEdit;\r
384 \r
385 % num value\r
386 oldv = get(hNumEdit, 'UserData');\r
387 newv = str2num(get(hNumEdit, 'String'));\r
388 if isempty(newv) | newv(1) < 1 | newv(1) > 100\r
389     newv = oldv;\r
390 end\r
391 set(hNumEdit, 'String', num2str(newv(1)));\r
392 set(hNumEdit, 'UserData', newv(1));\r
393 \r
394 setstatus(DemoFig, 'Press ''Generate'' button');\r
395 return;\r
396 \r
397 %%%\r
398 %%%  Sub-function - FeaturesUpdate\r
399 %%%\r
400 \r
401 function FeaturesUpdate(DemoFig)\r
402 if nargin<1\r
403    DemoFig = gcbf;\r
404 end;\r
405 \r
406 pointSize = 10; % size of point cross\r
407 width     = 2;  % width of cross lines\r
408 \r
409 handles = get(DemoFig,'UserData');\r
410 \r
411 hSrcAx     = handles.SrcAx;\r
412 hDstAx     = handles.DstAx;\r
413 \r
414 hSrcImage = handles.SrcImage;\r
415 hDstImage = handles.DstImage;\r
416 \r
417 hFeaturesA = get(hSrcAx, 'UserData');\r
418 hFeaturesB = get(hDstAx, 'UserData');\r
419 \r
420 featuresA = get(hSrcImage, 'UserData');\r
421 featuresB = get(hDstImage, 'UserData');\r
422 \r
423 delete(hFeaturesA(:));\r
424 delete(hFeaturesB(:));\r
425 hFeaturesA = [];\r
426 hFeaturesB = [];\r
427 % draw featuresA\r
428 for fnum = 1:size(featuresA,1)\r
429     hFeaturesA(2*fnum - 1) = line('Parent', hSrcAx, ...\r
430         'XData', [featuresA(fnum, 1)-pointSize featuresA(fnum, 1)+pointSize], ...\r
431         'YData', [featuresA(fnum, 2) featuresA(fnum, 2)], ...\r
432         'Color', 'blue', 'LineWidth', width);\r
433     hFeaturesA(2*fnum) = line('Parent', hSrcAx, ...\r
434         'XData', [featuresA(fnum, 1) featuresA(fnum, 1)], ...\r
435         'YData', [featuresA(fnum, 2)-pointSize featuresA(fnum, 2)+pointSize], ...\r
436         'Color', 'blue', 'LineWidth', width);\r
437 end\r
438 % draw featuresB\r
439 % If flow was not found, when red cross with featureA coordinates is drawn\r
440 for fnum = 1:size(featuresB,1)\r
441     if isnan(featuresB(fnum)) == 1\r
442         hFeaturesB(2*fnum - 1) = line('Parent', hDstAx, ...\r
443             'XData', [featuresA(fnum, 1)-pointSize featuresA(fnum, 1)+pointSize], ...\r
444             'YData', [featuresA(fnum, 2) featuresA(fnum, 2)], ...\r
445             'Color', 'red', 'LineWidth', width);\r
446         hFeaturesB(2*fnum) = line('Parent', hDstAx, ...\r
447             'XData', [featuresA(fnum, 1) featuresA(fnum, 1)], ...\r
448             'YData', [featuresA(fnum, 2)-pointSize featuresA(fnum, 2)+pointSize], ...\r
449             'Color', 'red', 'LineWidth', width);\r
450     else\r
451         hFeaturesB(2*fnum - 1) = line('Parent', hDstAx, ...\r
452             'XData', [featuresB(fnum, 1)-pointSize featuresB(fnum, 1)+pointSize], ...\r
453             'YData', [featuresB(fnum, 2) featuresB(fnum, 2)], ...\r
454             'Color', 'blue', 'LineWidth', width);\r
455         hFeaturesB(2*fnum) = line('Parent', hDstAx, ...\r
456             'XData', [featuresB(fnum, 1) featuresB(fnum, 1)], ...\r
457             'YData', [featuresB(fnum, 2)-pointSize featuresB(fnum, 2)+pointSize], ...\r
458             'Color', 'blue', 'LineWidth', width);\r
459     end\r
460 end\r
461 \r
462 set(hSrcAx, 'UserData', hFeaturesA);\r
463 set(hDstAx, 'UserData', hFeaturesB);\r
464 return;\r
465 \r
466 %%%\r
467 %%%  Sub-function - GetFeatures\r
468 %%%\r
469 \r
470 function GetFeatures(DemoFig)\r
471 if nargin<1\r
472    DemoFig = gcbf;\r
473 end;\r
474 \r
475 handles = get(DemoFig,'UserData');\r
476 \r
477 hSrcAx     = handles.SrcAx;\r
478 \r
479 hSrcImage = handles.SrcImage;\r
480 hDstImage = handles.DstImage;\r
481 \r
482 srcImage = get(hSrcImage, 'CData');\r
483 \r
484 featuresA = get(hSrcImage, 'UserData');\r
485 featuresB = get(hDstImage, 'UserData');\r
486 \r
487 set(hSrcImage, 'UserData', []);\r
488 set(hDstImage, 'UserData', []);\r
489 FeaturesUpdate(DemoFig);\r
490 \r
491 [x, y] = getpts(hSrcAx);\r
492 imgSize = [size(srcImage,2), size(srcImage,1)];\r
493 points = [x, y];\r
494 points(points(:,1)<1 | points(:,1) > imgSize(1) | ...\r
495     points(:,2)<1 | points(:,2) > imgSize(2) ,:) = [];\r
496 if ~isempty(points)\r
497     featuresA = points;\r
498     featuresB = [];\r
499     setstatus(DemoFig, 'Press ''Apply'' button');\r
500 end\r
501 set(hSrcImage, 'UserData', featuresA);\r
502 set(hDstImage, 'UserData', featuresB);\r
503 FeaturesUpdate(DemoFig);\r
504 return;\r
505 \r
506 %%%\r
507 %%%  Sub-function - GoodFeatures\r
508 %%%\r
509 \r
510 function GoodFeatures(DemoFig)\r
511 if nargin<1\r
512    DemoFig = gcbf;\r
513 end;\r
514 \r
515 handles = get(DemoFig,'UserData');\r
516 \r
517 hSrcAx    = handles.SrcAx;\r
518 hNumEdit  = handles.NumEdit;\r
519 hSrcImage = handles.SrcImage;\r
520 hDstImage = handles.DstImage;\r
521 \r
522 srcImage = get(hSrcImage, 'CData');\r
523 \r
524 featuresA = get(hSrcImage, 'UserData');\r
525 featuresB = get(hDstImage, 'UserData');\r
526 \r
527 set(hSrcImage, 'UserData', []);\r
528 set(hDstImage, 'UserData', []);\r
529 FeaturesUpdate(DemoFig);\r
530 \r
531 numFeatures = get(hNumEdit, 'UserData');\r
532 qualityLevel = 0.1;\r
533 minDistance  = size(srcImage, 1) / 5;\r
534 points = cvGoodFeaturesToTrack(srcImage, numFeatures, ...\r
535     qualityLevel, minDistance);\r
536 %points = [points(:, 2), points(:, 1)] + 1;\r
537 if ~isempty(points)\r
538     featuresA = points;\r
539     featuresB = [];\r
540     setstatus(DemoFig, 'Press ''Apply'' button');\r
541 else\r
542     setstatus(DemoFig, 'The features were not found');\r
543 end\r
544 set(hSrcImage, 'UserData', featuresA);\r
545 set(hDstImage, 'UserData', featuresB);\r
546 FeaturesUpdate(DemoFig);\r
547 return;