1 function flowdemo(action,varargin);
\r
2 % OpenCV Optical Flow functions demo
\r
5 demoName = 'OpenCV Optical Flow demo';
\r
7 action='InitializeDEMO';
\r
10 feval(action,varargin{:});
\r
15 %%% Sub-function - InitializeDEMO
\r
18 function InitializeDEMO()
\r
22 % If demo is already running, bring it to the foreground.
\r
23 h = findobj(allchild(0), 'tag', demoName);
\r
29 screenD = get(0, 'ScreenDepth');
\r
36 imgSize = [320, 240];
\r
37 ctrHt = 19; % controls' height
\r
39 %==================================
\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
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
57 %==================================
\r
58 % Set up the image axes
\r
59 row = figpos(4); col = figpos(3);
\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
72 title('Source Image');
\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
84 title('Destination Image');
\r
86 %==================================
\r
88 blank = repmat(uint8(0),imgSize(2),imgSize(1));
\r
89 hSrcImage = image('Parent', hSrcAx,...
\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
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
108 %====================================
\r
109 % Information for all buttons (and menus)
\r
113 %====================================
\r
114 % The CONSOLE frame
\r
115 frmBorder=0.5 * ctrHt;
\r
116 dstImgPos = get(hDstAx, 'Position');
\r
118 frmColor = [0.45, 0.45, 0.45];
\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
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
134 %====================================
\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
150 %====================================
\r
153 callbackStr='close(gcf)';
\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
165 c = get(DemoFig,'Color');
\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
182 srcImgPos = get(hSrcAx, 'Position');
\r
184 %====================================
\r
185 % The Good Features frame
\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
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
202 %====================================
\r
203 % The Good Features Label
\r
204 pos = [frmLeft+frmBorder, frmBottom + frmHeight - ctrHt-1, ...
\r
205 frmWidth-2*frmBorder, ctrHt];
\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
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
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
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
247 'Horiz', 'right',...
\r
248 'Tag','AppEdit', ...
\r
249 'UserData', [20], ...
\r
250 'Callback','flowdemo(''ControlsUpdate'')');
\r
252 %====================================
\r
253 % The Generate button
\r
254 labelStr='Generate';
\r
255 callbackStr='flowdemo(''GoodFeatures'')';
\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
267 setstatus(DemoFig, 'Initializing Demo...');
\r
268 set(DemoFig, 'Pointer', 'watch');
\r
270 set(DemoFig, 'Visible','on');
\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
276 handles.SrcAx = hSrcAx;
\r
277 handles.DstAx = hDstAx;
\r
279 handles.NumEdit = hNumEdit;
\r
281 set(DemoFig, 'UserData', handles);
\r
283 LoadNewImage(DemoFig);
\r
285 set(DemoFig, 'HandleVisibility','Callback')
\r
286 set([closeHndl applyHndl genHndl], 'Enable', 'on');
\r
291 %%% Sub-Function - LoadNewImage
\r
294 function LoadNewImage(DemoFig)
\r
300 set(DemoFig,'Pointer','watch');
\r
302 handles = get(DemoFig,'UserData');
\r
304 hSrcImage = handles.SrcImage;
\r
305 hDstImage = handles.DstImage;
\r
309 load cvdemos rock1 rock2;
\r
312 load cvdemos lkrock1;
\r
315 featuresA = lkrock1(1:10:200,:);
\r
316 set(hSrcImage, 'Cdata', img);
\r
317 set(hSrcImage, 'UserData', featuresA);
\r
320 set(hDstImage, 'Cdata', img);
\r
321 set(hDstImage, 'UserData', []);
\r
325 setstatus(DemoFig, 'Press ''Apply'' button');
\r
331 %%% Sub-Function - Apply
\r
334 function Apply(DemoFig)
\r
340 handles = get(DemoFig,'UserData');
\r
342 hSrcImage=handles.SrcImage;
\r
343 hDstImage=handles.DstImage;
\r
345 set(DemoFig,'Pointer','watch');
\r
346 setstatus(DemoFig, 'Calculating flow...'); drawnow;
\r
348 srcImage = get(hSrcImage, 'CData');
\r
349 dstImage = get(hDstImage, 'CData');
\r
351 featuresA = get(hSrcImage, 'UserData');
\r
353 winSize = [10, 10];
\r
355 criteria = [20, 0.03];
\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
363 set(hDstImage, 'UserData', featuresB);
\r
364 FeaturesUpdate(DemoFig);
\r
366 setstatus(DemoFig, 'Done');
\r
367 set(DemoFig,'Pointer','arrow'); drawnow
\r
372 %%% Sub-function - ControlsUpdate
\r
375 function ControlsUpdate(DemoFig)
\r
381 handles = get(DemoFig,'UserData');
\r
383 hNumEdit = handles.NumEdit;
\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
391 set(hNumEdit, 'String', num2str(newv(1)));
\r
392 set(hNumEdit, 'UserData', newv(1));
\r
394 setstatus(DemoFig, 'Press ''Generate'' button');
\r
398 %%% Sub-function - FeaturesUpdate
\r
401 function FeaturesUpdate(DemoFig)
\r
406 pointSize = 10; % size of point cross
\r
407 width = 2; % width of cross lines
\r
409 handles = get(DemoFig,'UserData');
\r
411 hSrcAx = handles.SrcAx;
\r
412 hDstAx = handles.DstAx;
\r
414 hSrcImage = handles.SrcImage;
\r
415 hDstImage = handles.DstImage;
\r
417 hFeaturesA = get(hSrcAx, 'UserData');
\r
418 hFeaturesB = get(hDstAx, 'UserData');
\r
420 featuresA = get(hSrcImage, 'UserData');
\r
421 featuresB = get(hDstImage, 'UserData');
\r
423 delete(hFeaturesA(:));
\r
424 delete(hFeaturesB(:));
\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
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
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
462 set(hSrcAx, 'UserData', hFeaturesA);
\r
463 set(hDstAx, 'UserData', hFeaturesB);
\r
467 %%% Sub-function - GetFeatures
\r
470 function GetFeatures(DemoFig)
\r
475 handles = get(DemoFig,'UserData');
\r
477 hSrcAx = handles.SrcAx;
\r
479 hSrcImage = handles.SrcImage;
\r
480 hDstImage = handles.DstImage;
\r
482 srcImage = get(hSrcImage, 'CData');
\r
484 featuresA = get(hSrcImage, 'UserData');
\r
485 featuresB = get(hDstImage, 'UserData');
\r
487 set(hSrcImage, 'UserData', []);
\r
488 set(hDstImage, 'UserData', []);
\r
489 FeaturesUpdate(DemoFig);
\r
491 [x, y] = getpts(hSrcAx);
\r
492 imgSize = [size(srcImage,2), size(srcImage,1)];
\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
499 setstatus(DemoFig, 'Press ''Apply'' button');
\r
501 set(hSrcImage, 'UserData', featuresA);
\r
502 set(hDstImage, 'UserData', featuresB);
\r
503 FeaturesUpdate(DemoFig);
\r
507 %%% Sub-function - GoodFeatures
\r
510 function GoodFeatures(DemoFig)
\r
515 handles = get(DemoFig,'UserData');
\r
517 hSrcAx = handles.SrcAx;
\r
518 hNumEdit = handles.NumEdit;
\r
519 hSrcImage = handles.SrcImage;
\r
520 hDstImage = handles.DstImage;
\r
522 srcImage = get(hSrcImage, 'CData');
\r
524 featuresA = get(hSrcImage, 'UserData');
\r
525 featuresB = get(hDstImage, 'UserData');
\r
527 set(hSrcImage, 'UserData', []);
\r
528 set(hDstImage, 'UserData', []);
\r
529 FeaturesUpdate(DemoFig);
\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
540 setstatus(DemoFig, 'Press ''Apply'' button');
\r
542 setstatus(DemoFig, 'The features were not found');
\r
544 set(hSrcImage, 'UserData', featuresA);
\r
545 set(hDstImage, 'UserData', featuresB);
\r
546 FeaturesUpdate(DemoFig);
\r