Move the sources to trunk
[opencv] / apps / StereoDemo / mainfltk.cpp
1 /*
2  * compile on Unix using:
3  gcc `pkg-config --cflags --libs opencv` \
4     `fltk-config --cxxflags --ldflags --libs` -DFLTK \
5     mainfltk.cpp  main.cpp -o stereodemofltk
6 */
7 #ifdef FLTK
8 #include "cvaux.h"
9 #include "cvfltk.h"
10 #include <string.h>
11 #include <stdio.h>
12 #include <math.h>
13 #include <time.h>
14 #include "highgui.h"
15
16
17 //********************** Calibration parameters **************************
18 extern CvCalibFilter CalibFilter;
19 extern double EtalonParams[3];
20 extern int prev_time;
21 //************************************************************************
22
23
24 typedef struct 
25 {
26     char* name;
27     int type;
28     int minimum;
29     int maximum;
30     int step;
31     void* value;
32 } Parameter;
33
34 #define TYPE_RANGE 1
35 #define TYPE_BOOL 2
36
37 /*parameters*/
38 int max_disp;
39
40 Parameter BirchfieldParams[] = { {"maxdisp", TYPE_RANGE, 1, 150, 1, &max_disp},
41                                  0 };   
42
43
44 char* methods_names[] = {"Modified Birchfield", 0 };
45 Parameter* methods_params[] = {BirchfieldParams, 0};
46                                                                  
47 class VideoWindow;
48
49 Fl_Window *root_window=(Fl_Window *)0;
50 VideoWindow* video_window_left = 0;
51 VideoWindow* video_window_right = 0;
52 VideoWindow* video_window_disp = 0;  
53
54 CvCapture* capture_left = 0;
55 CvCapture* capture_right = 0;
56
57 CvVideoWriter* writer_left = 0;
58 CvVideoWriter* writer_right = 0;
59 CvVideoWriter* writer_disp = 0;
60
61 static int started = 0;
62 double timeout = 0.005;
63 IplImage* video_image_left = 0;
64 IplImage* video_image_right = 0;
65 IplImage* video_image_disp = 0;
66 IplImage* disp_image = 0;
67 IplImage* lg = 0;
68 IplImage* rg = 0;
69
70 double old_pos = 0;
71 Fl_Value_Slider* video_pos = 0;
72 Fl_Check_Button* do_stereo_button = 0;
73 Fl_Check_Button* rectify_button = 0;
74 Fl_Check_Button* half_size_button = 0;
75
76 int guard = 0;
77 int is_avi = 0;
78 int is_recorded = 0;
79 double fps = -1;
80 double fps_alpha = 0.1;
81 char fps_buffer[100];
82 double cpu_freq = 0;
83 double prev_frame_stamp = 0;
84 int start_pos = 0;
85 int total_frames0 = 0;
86 int total_frames = 0;
87 int is_loopy = 0;
88
89 int cur_method = 0;
90
91 Fl_Button* stop_button = 0;
92 Fl_Button* play_button = 0;
93 Fl_Button* video_button = 0;
94 Fl_Button* cam_button = 0;
95 Fl_Button* record_button = 0;
96 Fl_Box* fps_box = 0;
97
98 Fl_Button* calib_button = 0;
99 Fl_Button* savecam_button = 0;
100 Fl_Button* loadcam_button = 0;
101 Fl_Button* swapcam_button = 0;
102
103 Fl_Value_Slider* max_disp_slider = 0;
104
105 Fl_Tabs* tabs = 0;
106
107 class VideoWindow : public Fl_Box
108 {
109 public:
110     VideoWindow( int x, int y, int w, int h, const char* t = 0 );
111     ~VideoWindow();
112     void draw();
113 };
114
115 VideoWindow::VideoWindow( int x, int y, int w, int h, const char* t ):
116     Fl_Box( x, y, w, h, t )
117 {
118 }
119
120 VideoWindow::~VideoWindow()
121 {
122 }
123
124 void VideoWindow::draw()
125 {
126 }
127
128 static void end_capture()
129 {
130     started = 0;
131     cvReleaseCapture( &capture_left );
132     cvReleaseCapture( &capture_right );
133 }
134
135 static void cb_Stop( Fl_Widget*, void* );
136 static void cb_StartStopRecord( Fl_Widget*, void* );
137 static void cb_Exit( Fl_Widget*, void* );
138
139 static double get_time_accurate(void)
140 {
141     return (double)cvGetTickCount()*1e-3/(cpu_freq+1e-10);
142 }
143
144 IplImage* stereo( IplImage* left, IplImage* right )
145 {
146     if( lg && (left->width != lg->width || left->height != lg->height) )
147     {
148         cvReleaseImage(&lg); lg = NULL;
149     }
150     if( rg && (right->width != rg->width || right->height != rg->height) )
151     {
152         cvReleaseImage(&rg); rg = NULL;
153     }
154     if( disp_image && (left->width != disp_image->width || left->height != disp_image->height ))
155     {
156         cvReleaseImage(&disp_image); disp_image = NULL;
157     }
158
159     if( !disp_image )
160         disp_image = cvCreateImage( cvSize(left->width, left->height),
161                                     IPL_DEPTH_8U, 1 );
162     if( !lg )
163         lg = cvCreateImage( cvSize(left->width, left->height),
164                                     IPL_DEPTH_8U, 1 );
165     if( !rg )
166         rg = cvCreateImage( cvSize(right->width, right->height),
167                                     IPL_DEPTH_8U, 1 );
168
169     switch( cur_method )
170     {
171     case 0: //Moodified Birchfield
172         cvCvtColor( left,lg, CV_BGR2GRAY );
173         cvCvtColor( right,rg, CV_BGR2GRAY );
174         cvSet(disp_image, cvScalar(0,0,0,0) );
175
176         if( half_size_button->value() )
177         {
178             IplImage* hl = cvCreateImage(cvSize(lg->width/2, lg->height/2),
179                                      lg->depth, lg->nChannels );
180             IplImage* hr = cvCreateImage(cvSize(rg->width/2, rg->height/2),
181                                          rg->depth, rg->nChannels );
182             IplImage* hd = cvCreateImage(cvSize(disp_image->width/2, disp_image->height/2),
183                                          disp_image->depth, disp_image->nChannels );
184         
185             cvResize( lg,hl);
186             cvResize( rg,hr);
187             cvSet(hd, cvScalar(0,0,0,0) );
188             
189             cvFindStereoCorrespondence( 
190                    hl, hr,
191                    CV_DISPARITY_BIRCHFIELD,
192                    hd,
193                    max_disp ); 
194             
195             cvConvertScale( hd, hd, 255./max_disp );
196
197             cvResize( hd, disp_image );
198
199             cvReleaseImage(&hl);
200             cvReleaseImage(&hr);
201             cvReleaseImage(&hd);
202         }
203         else
204         {
205             cvFindStereoCorrespondence( 
206                    lg, rg,
207                    CV_DISPARITY_BIRCHFIELD,
208                    disp_image,
209                    max_disp );
210         
211             cvConvertScale(disp_image, disp_image, 255./max_disp);
212         }
213
214         break;
215     default: 
216         break;
217     }  
218     return disp_image;
219 }
220
221 void show_images()
222 {
223     uchar* data = 0;
224     int step = 0;
225     CvSize size;
226     cvGetRawData( video_image_left, &data, &step, &size );
227
228     video_window_left->redraw();
229     fl_draw_image( (uchar*)data, video_window_left->x(), video_window_left->y(),
230                    size.width, size.height, 3, step );
231
232     cvGetRawData( video_image_right, &data, &step, &size );
233
234     video_window_right->redraw();
235     fl_draw_image( (uchar*)data, video_window_right->x(), video_window_right->y(),
236                    size.width, size.height, 3, step );  
237 }
238        
239 static void get_next_frame(void*)
240 {
241     static int repositioning = 0;
242     IplImage* frame_left = 0;
243     IplImage* frame_right = 0;
244
245     double new_pos = video_pos->value();
246     if( (new_pos-old_pos >= 1e-10 || new_pos-old_pos <= -1e-10) && !repositioning)
247     {
248         video_window_left->redraw();
249         video_window_right->redraw();
250         
251         cvSetCaptureProperty( capture_left, CV_CAP_PROP_POS_AVI_RATIO, new_pos );
252         cvSetCaptureProperty( capture_right, CV_CAP_PROP_POS_AVI_RATIO, new_pos );
253         new_pos = cvGetCaptureProperty( capture_left, CV_CAP_PROP_POS_AVI_RATIO );
254         printf("Repositioning\n");
255         repositioning = 1;
256     }
257     else
258     {
259         new_pos = cvGetCaptureProperty( capture_left, CV_CAP_PROP_POS_AVI_RATIO );
260         video_pos->value(new_pos);
261         repositioning = 0;
262     }
263     old_pos = new_pos;
264     frame_left = cvQueryFrame( capture_left );
265     frame_right = cvQueryFrame( capture_right );
266
267     if( (frame_left == 0 || frame_right == 0) && is_avi )
268     {
269         cb_Stop(0,0);
270         return;
271     }
272
273     if( video_window_left && frame_left &&
274         video_window_right && frame_right )
275     {
276         //resize video window if it is less than required
277         if( video_window_left->w() < frame_left->width || video_window_left->h() < frame_left->height || 
278             video_window_right->w() < frame_right->width || video_window_right->h() < frame_right->height  )
279             root_window->size( (short)(frame_left->width + frame_right->width + 30), (short)(MAX(frame_left->height,frame_right->height) + 150));
280         
281         //draw left images
282         CvRect rect = { video_window_left->x(), video_window_left->y(),
283                         frame_left->width, frame_left->height };
284         CvRect rect2 = { video_window_right->x(), video_window_right->y(),
285                         frame_right->width, frame_right->height };
286         
287         if( !video_image_left || video_image_left->width < rect.width ||
288             video_image_left->height < rect.height )
289         {
290             cvReleaseImage( &video_image_left );
291             video_image_left = cvCreateImage( cvSize( rect.width, rect.height ), 8, 3 );
292         }
293
294         cvSetImageROI( video_image_left, cvRect(0,0,rect.width, rect.height));
295         cvFlip( frame_left, video_image_left, 0 );
296         
297         if( writer_left && is_recorded )
298         {
299             cvWriteFrame( writer_left, video_image_left );
300         }
301         cvCvtColor( video_image_left, video_image_left, CV_RGB2BGR );
302         
303         if( !video_image_right || video_image_right->width < rect2.width ||
304             video_image_right->height < rect2.height )
305         {
306             cvReleaseImage( &video_image_right );
307             video_image_right = cvCreateImage( cvSize( rect2.width, rect2.height ), 8, 3 );
308         }
309
310         cvSetImageROI( video_image_right, cvRect(0,0,rect2.width, rect2.height));
311         cvFlip( frame_right, video_image_right, 0 );
312
313         if( writer_right && is_recorded )
314         {
315             cvWriteFrame( writer_right, video_image_right );
316         } 
317         cvCvtColor( video_image_right, video_image_right, CV_RGB2BGR );
318
319         if( calib_button->value() )
320         {
321             IplImage* images[2] = { video_image_left, video_image_right };
322             bool found = CalibFilter.FindEtalon( images );
323             //if( !save )
324                 CalibFilter.DrawPoints( images );
325
326             if( found )
327             {
328                 int cur_time = clock();
329                 if( cur_time >= prev_time + 1000 )
330                 {
331                     prev_time = cur_time;
332                     CalibFilter.Push();
333                     cvXorS( images[0], cvScalarAll(255), images[0] );
334                     cvXorS( images[1], cvScalarAll(255), images[1] );
335                     //g_undistort = 0;
336                 }
337
338                 if( CalibFilter.IsCalibrated() )
339                 {
340                     calib_button->clear();
341                     rectify_button->activate();
342                     savecam_button->activate();
343
344                     //g_undistort = 1;
345                     //g_rectify = 1;
346                 }
347             }
348         }
349         if( CalibFilter.IsCalibrated() && rectify_button->value() )
350         {
351             IplImage* images[2] = { video_image_left, video_image_right };
352             CalibFilter.Rectify( images, images );
353         }     
354
355         //Running stereo algorithm
356         //draw disparity window
357         if( do_stereo_button->value() && video_window_disp  )
358         {
359             IplImage* disp; 
360             disp = stereo(video_image_left, video_image_right);
361         
362             if( disp ) 
363             {     
364                 CvRect rect = { video_window_disp->x(), video_window_disp->y(),
365                             disp->width, disp->height };
366
367                 if( !video_image_disp || video_image_disp->width < rect.width ||
368                     video_image_disp->height < rect.height )
369                 {
370                     cvReleaseImage( &video_image_disp );
371                     video_image_disp = cvCreateImage( cvSize( rect.width, rect.height ), 8, 3 );
372                 }
373
374                 if( disp->nChannels != 3 )
375                 {
376                     cvCvtColor( disp, video_image_disp, CV_GRAY2BGR );
377                 }
378                 else
379                 {
380                     cvCopy( disp, video_image_disp );
381                 }
382
383                 if( writer_disp && is_recorded )
384                 {
385                     cvWriteFrame( writer_disp, video_image_disp );
386                 } 
387         
388
389                 uchar* data = 0;
390                 int step = 0;
391                 CvSize size;
392                 cvGetRawData( video_image_disp, &data, &step, &size );
393
394                 video_window_disp->redraw();
395                 fl_draw_image( (uchar*)data, video_window_disp->x(), video_window_disp->y(),
396                                size.width, size.height, 3, step );  
397             }
398         }   
399         show_images();
400
401     }           
402
403     if( started )
404     {
405         double cur_frame_stamp = get_time_accurate();
406         // update fps
407         if( fps < 0 )
408             fps = 1000/(cur_frame_stamp - prev_frame_stamp);
409         else
410             fps = (1-fps_alpha)*fps + fps_alpha*1000/(cur_frame_stamp - prev_frame_stamp);
411         prev_frame_stamp = cur_frame_stamp;
412         sprintf( fps_buffer, "FPS: %5.1f", fps );
413         fps_box->label( fps_buffer );
414         fps_box->redraw();
415         if( total_frames > 0 )
416         {
417             if( --total_frames == 0 )
418                 if( !is_loopy )
419                     cb_Exit(0,0);
420                 else
421                 {
422                     total_frames = total_frames0;
423                     cvSetCaptureProperty( capture_left, CV_CAP_PROP_POS_FRAMES, start_pos );
424                     cvSetCaptureProperty( capture_right, CV_CAP_PROP_POS_FRAMES, start_pos );
425                 }
426         }
427         Fl::add_timeout( timeout, get_next_frame, 0 );
428     }
429 }
430
431 static void cb_PauseResume( Fl_Widget*, void* )
432 {
433     video_button->deactivate();
434     cam_button->deactivate();
435     stop_button->activate();
436
437     if( !started )
438     {
439         started = 1;
440         play_button->label("@||");
441         play_button->activate();
442         play_button->redraw();
443         stop_button->activate();
444         stop_button->redraw();
445         record_button->activate();
446
447         video_window_left->redraw();
448         video_window_right->redraw();
449         
450         prev_frame_stamp = get_time_accurate();
451         Fl::add_timeout( timeout, get_next_frame, 0 );
452     }
453     else
454     {
455         started = 0;
456         play_button->label("@>");
457         play_button->redraw();
458     }
459 }
460
461
462 static void cb_Stop( Fl_Widget*, void* )
463 {
464     if( started )
465         cb_PauseResume(0,0);
466     if( is_recorded )
467         cb_StartStopRecord(0,0);
468     cvSetCaptureProperty( capture_left, CV_CAP_PROP_POS_AVI_RATIO, 0 );
469     cvSetCaptureProperty( capture_right, CV_CAP_PROP_POS_AVI_RATIO, 0 );
470     video_button->activate();
471     cam_button->activate();
472     stop_button->deactivate();
473     record_button->deactivate();
474 }
475
476 static void cb_StartAVI( const char* newfile_left, const char* newfile_right,
477                          int start_pos, int was_started )
478 {
479     if( newfile_left != 0 && newfile_right != 0)
480     {
481         end_capture();
482         capture_left = cvCaptureFromAVI( newfile_left );
483         capture_right = cvCaptureFromAVI( newfile_right );
484
485         if( capture_left && capture_right )
486         {
487             was_started = 1;
488             if( start_pos != 0 )
489             {   
490                 cvSetCaptureProperty( capture_left, CV_CAP_PROP_POS_FRAMES, start_pos );
491                 cvSetCaptureProperty( capture_right, CV_CAP_PROP_POS_FRAMES, start_pos );
492             }
493         }
494         is_avi = 1;
495     }
496
497     if( was_started )
498         cb_PauseResume(0,0);
499 }
500
501 static void cb_LoadImages( const char* filename1, const char* filename2 )
502 {
503     if( video_image_left )
504         cvReleaseImage( &video_image_left );
505     if( video_image_right )
506         cvReleaseImage( &video_image_right );
507     if( video_image_disp )
508         cvReleaseImage( &video_image_disp );   
509
510     video_image_left = cvLoadImage( filename1, 1 );
511     video_image_right = cvLoadImage( filename2, 1 );
512 }
513
514 static void cb_Open( Fl_Widget*, void* )
515 {
516     char filename1[1000];
517     filename1[0] = '\0';
518     char filename2[1000];
519     filename2[0] = '\0';
520     int was_started = 0;
521     if( started )
522     {
523         was_started = 1;
524         cb_PauseResume(0,0);
525     }
526     char *newfile = fl_file_chooser("Open Left File", "*", NULL);
527     if( newfile ) 
528     {
529         strcpy( filename1, newfile );
530         newfile = fl_file_chooser("Open Right File", "*", NULL);
531         if( newfile )
532         {
533             strcpy( filename2, newfile );
534
535             //TODO: add bitmap files processing
536             char* point = strrchr( filename1, '.' );
537             if( !strcmp( point, ".avi" ) )
538                 cb_StartAVI( filename1, filename2, 0, was_started );
539             else if( !strcmp( point, ".bmp" ) )
540                 cb_LoadImages( filename1, filename2 );
541         }
542     }
543 }
544
545 void cb_LoadCamera( Fl_Widget*, void* )
546 {
547     cb_PauseResume(0,0);
548
549     char filename[1000];
550     filename[0] = '\0';
551     char *newfile = fl_file_chooser("Load Camera Parameters", "*", filename);
552
553     if( newfile ) 
554     {
555         CalibFilter.LoadCameraParams( newfile );
556         rectify_button->activate();
557     }
558     cb_PauseResume(0,0);
559 }
560
561 void cb_SaveCamera( Fl_Widget*, void* )
562 {
563     cb_PauseResume(0,0);
564
565     char filename[1000];
566     filename[0] = '\0';
567     char *newfile = fl_file_chooser("Save Camera Parameters", "*", filename);
568
569     if( newfile ) CalibFilter.SaveCameraParams( newfile );
570
571     cb_PauseResume(0,0);
572
573 }
574
575
576 void cb_StartCam( Fl_Widget*, void* )
577 {
578     if( started )
579         cb_PauseResume(0,0);
580     end_capture();
581 #ifdef WIN32    
582     Sleep(10);
583 #endif    
584     is_avi = 0;
585     capture_left = cvCaptureFromCAM( /*100*/-1 );
586     capture_right = cvCaptureFromCAM( /*101*/-1 );
587     cb_PauseResume(0,0);
588 }
589
590
591 static void cb_StartStopRecord( Fl_Widget*, void* )
592 {       
593     if( !is_recorded )
594     {
595         cb_PauseResume(0,0);
596
597
598         if( video_image_left )
599         {
600             char *newfile = fl_file_chooser("Left File", "*", NULL);
601             writer_left = NULL;
602             if( newfile ) 
603             { 
604                 writer_left = cvCreateVideoWriter( newfile, -1, 15, cvGetSize( video_image_left ));
605             }
606             if( writer_left )
607             {
608                 record_button->box( FL_DOWN_BOX );
609                 is_recorded = 1;
610             }
611         }
612         if( video_image_right )
613         {
614             char *newfile = fl_file_chooser("Right File", "*", NULL);
615             writer_right = cvCreateVideoWriter( newfile, -1, 15, cvGetSize( video_image_left ));
616             if( writer_right )
617             {
618                 record_button->box( FL_DOWN_BOX );
619                 is_recorded = 1;
620             }
621         }
622         if( video_image_disp )
623         {
624             char *newfile = fl_file_chooser("Disparity File", "*", NULL);
625             writer_disp = cvCreateVideoWriter( newfile, -1, 15, cvGetSize( video_image_disp ));
626             if( writer_disp )
627             {
628                 record_button->box( FL_DOWN_BOX );
629                 is_recorded = 1;
630             }
631         }  
632         cb_PauseResume(0,0);
633     }
634     else
635     {
636         record_button->box( FL_UP_BOX );
637         cvReleaseVideoWriter( &writer_left );
638         cvReleaseVideoWriter( &writer_right );  
639         cvReleaseVideoWriter( &writer_disp ); 
640
641         is_recorded = 0;
642     }
643 }
644
645 static void cb_AutoRun( void* _aviname )
646 {
647     char* aviname_left = (char*)_aviname;
648     char* aviname_right = (char*)_aviname;
649
650
651    /* char* ext_pos = strrchr( aviname, '.' );
652     if( ext_pos )
653     {
654         char* colon_pos = strchr( ext_pos, ':' );
655         if( colon_pos )
656         {
657             *colon_pos = '\0';
658             start_pos = strtoul( colon_pos+1, &colon_pos, 10 );
659             if( colon_pos && *colon_pos == ':' )
660                 total_frames0 = total_frames = strtoul( colon_pos+1, &colon_pos, 10 );
661             if( colon_pos && *colon_pos == ':' )
662                 is_loopy = 1;
663         }
664     }*/
665
666     cb_StartAVI( aviname_left, aviname_right, start_pos, 0 );
667 }
668
669
670 static void cb_Exit( Fl_Widget*, void* )
671 {
672     cvReleaseCapture( &capture_left );
673     cvReleaseCapture( &capture_right );
674     cvReleaseVideoWriter( &writer_left );
675     cvReleaseVideoWriter( &writer_right );
676     cvReleaseVideoWriter( &writer_disp ); 
677     exit(0);
678 }
679
680
681 static void cb_OnSlider( Fl_Widget* slider, void* value)
682 {
683     *((int*)value) = ((Fl_Slider*)slider)->value();
684
685     //recompute stereo on current frame 
686     if(!started && video_image_left && video_image_right)
687     {
688         IplImage* disp = stereo(video_image_left, video_image_right);
689             
690         if( disp ) 
691         {     
692             CvRect rect = { video_window_disp->x(), video_window_disp->y(),
693                         disp->width, disp->height };
694     
695             if( !video_image_disp || video_image_disp->width < rect.width ||
696                 video_image_disp->height < rect.height )
697             {
698                 cvReleaseImage( &video_image_disp );
699                 video_image_disp = cvCreateImage( cvSize( rect.width, rect.height ), 8, 3 );
700             }
701
702             if( disp->nChannels != 3 )
703             {                   
704                 cvCvtColor( disp, video_image_disp, CV_GRAY2BGR );
705             }
706             else
707             {
708                 cvCopy( disp, video_image_disp );
709             }
710
711             uchar* data = 0;
712             int step = 0;
713             CvSize size;
714             cvGetRawData( video_image_disp, &data, &step, &size );
715
716             video_window_disp->redraw();
717             fl_draw_image( (uchar*)data, video_window_disp->x(), video_window_disp->y(),
718                            size.width, size.height, 3, step ); 
719             show_images();
720         }
721     }
722
723
724 }
725
726 static void cb_OnMethod( Fl_Widget* tab, void* )
727 {
728      Fl_Group* v= (Fl_Group*)((Fl_Tabs*)tab)->value();
729      //Compare tab label with method name
730      const char* tab_name = v->label();
731
732      cur_method = -1;
733      for( int i = 0; methods_names[i]; i++)
734      {
735          if(!strcmp( tab_name, methods_names[i]) )
736          {
737              cur_method = i;
738          }          
739      }
740 }
741
742 static void cb_Calibrate( Fl_Widget* button, void* )
743 {
744      Fl_Button* v= ((Fl_Button*)button);
745      v->value(!v->value());
746
747
748 static void cb_Swap( Fl_Widget* , void* )
749 {
750     CvCapture* tmp = capture_left;
751     capture_left = capture_right;
752     capture_right = tmp;
753 }   
754
755 const int root_w = 320*3+30, 
756           root_h = 240 /*image*/ + 100/*play controls*/+ 150/*method tabs*/ + 30;
757
758 int main( int argc, char **argv )
759 {
760     char* aviname_left = 0;
761     char* aviname_right = 0;
762     int auto_run = 0;
763
764     if( argc == 3 )
765     {
766         aviname_left = argv[1];
767         aviname_right = argv[2];
768         auto_run = 1;
769     }
770     cpu_freq = cvGetTickFrequency(); 
771     printf("Processor frequency: %g\n", cpu_freq );
772
773     CalibFilter.SetEtalon( CV_CALIB_ETALON_CHESSBOARD, EtalonParams );
774     CalibFilter.SetCameraCount(2);
775     CalibFilter.SetFrames(15);
776
777
778     Fl_Window* w;
779     {
780         Fl_Window* o = root_window = new Fl_Window( root_w, root_h );
781         w = o;
782         {
783             Fl_Tabs* o = new Fl_Tabs( 10, 10, root_w - 20, root_h - 250 );
784             // camera tab
785             {
786                 Fl_Group* o = new Fl_Group( 10, 30, root_w - 20, root_h - 250, "Stereo" );
787                 {
788                     //left window
789                     VideoWindow* o = new VideoWindow( 15, 35, (root_w - 30) / 3, root_h - 120 );
790                     video_window_left = o;
791                     o->box( FL_BORDER_BOX );
792                     o->color(0);
793
794                     //right window
795                     o = new VideoWindow( 15 + (root_w - 30)/3, 35, (root_w - 30)/3, root_h - 120 );
796                     video_window_right = o;
797                     o->box( FL_BORDER_BOX );
798                     o->color(0); 
799
800                     //disparity window
801                     o = new VideoWindow( 15 + (root_w - 30)/3*2, 35, (root_w - 30)/3, root_h - 120 );
802                     video_window_disp = o;
803                     o->box( FL_BORDER_BOX );
804                     o->color(0); 
805                 }
806                 o->end();
807             }
808             o->end();
809             Fl_Group::current()->resizable(o);
810         }
811         //tabs with different stereo methods
812         {
813             Fl_Tabs* o = new Fl_Tabs( 10, root_h - 230, root_w - 20, 150 );
814             tabs = o;
815             o->callback(cb_OnMethod);
816             {
817                 for( int i = 0; methods_params[i]; i++ )
818                 {
819                     Fl_Group* o = new Fl_Group( 10, root_h - 210, root_w - 20, 150, methods_names[i] );
820                     {
821                         //create controls for current method
822                         for( int j = 0; methods_params[i][j].name; j++ )
823                         {
824                             switch( methods_params[i][j].type )
825                             {
826                             case TYPE_RANGE:{
827                                 Fl_Value_Slider* o = new Fl_Value_Slider( 15,root_h - 200 + j * 40, 200, 20, methods_params[i][j].name );
828                                 o->type( FL_HOR_NICE_SLIDER );
829                                 o->minimum(methods_params[i][j].minimum);
830                                 o->maximum(methods_params[i][j].maximum);
831                                 o->step(1);
832                                 o->callback(cb_OnSlider, methods_params[i][j].value );
833                                 *((int*)(methods_params[i][j].value)) = methods_params[i][j].minimum;
834
835                                 break;    }
836                             case TYPE_BOOL:
837                                 break;
838                             default: assert(0);
839                             }
840                         }                        
841                     }
842                     o->end();
843                 }
844                 {
845                     //camera calibration tab
846                     Fl_Group* o = new Fl_Group( 10, root_h - 210, root_w - 20, 150, "Camera" );
847                     {
848                         const int bwidth = 30, bheight = 30;
849                         calib_button = new Fl_Button( 10 + bwidth, root_h - 200, bwidth, bheight, "C" );
850                         calib_button->callback( cb_Calibrate );
851                         savecam_button = new Fl_Button( 10 + bwidth*2, root_h - 200, 2*bwidth, bheight, "Save" );
852                         loadcam_button = new Fl_Button( 10 + bwidth*4, root_h - 200, 2*bwidth, bheight, "Load" );
853                         savecam_button->callback(cb_SaveCamera);
854                         savecam_button->deactivate();
855                         loadcam_button->callback(cb_LoadCamera);
856                         swapcam_button = new Fl_Button( 10 + bwidth*6, root_h - 200, bwidth, bheight, "@<->" );
857                         swapcam_button->callback(cb_Swap);
858                     }
859                     o->end();
860                  }
861
862             }
863             o->end();                         
864         }
865
866         {
867             const int bwidth = 30, bheight = 30;
868             play_button = new Fl_Button( 10, root_h - 35, bwidth, bheight, "@>" );
869             play_button->callback((Fl_Callback*)cb_PauseResume);
870             play_button->deactivate();
871             stop_button = new Fl_Button( 10 + bwidth, root_h - 35, bwidth, bheight, "@square" );
872             stop_button->callback((Fl_Callback*)cb_Stop);
873             stop_button->deactivate();
874             video_button = new Fl_Button( 10 + bwidth*2, root_h - 35, bwidth, bheight, "..." );
875             video_button->callback((Fl_Callback*)cb_Open);
876             cam_button = new Fl_Button( 10 + bwidth*3, root_h - 35, bwidth, bheight, "[o]" );
877             cam_button->callback((Fl_Callback*)cb_StartCam);
878             video_pos = new Fl_Value_Slider( 10 + bwidth*4 + 10, root_h - 35, 200, 20, "Position" );
879             video_pos->type( FL_HOR_NICE_SLIDER );
880             record_button = new Fl_Button( 10 + bwidth*4 + 230, root_h - 35, bwidth, bheight, "@circle" );
881             record_button->labelcolor(FL_RED);
882             record_button->callback((Fl_Callback*)cb_StartStopRecord );
883             record_button->deactivate();
884             fps_box = new Fl_Box( 10, root_h - 75, bwidth*4, bheight, "<No data>" );
885             fps_box->box( FL_DOWN_BOX );
886
887             do_stereo_button = new Fl_Check_Button( 10 + bwidth*4 + 270, root_h - 35, 4*bwidth, bheight, "CalcStereo" );
888             rectify_button = new Fl_Check_Button( 10 + bwidth*4 + 370, root_h - 35, 4*bwidth, bheight, "Rectify" );
889             rectify_button->deactivate();
890             half_size_button = new Fl_Check_Button( 10 + bwidth*4 + 470, root_h - 35, 4*bwidth, bheight, "Use half size" );
891         }
892         o->end();
893     }
894     Fl::visual(FL_RGB);
895     w->show(argc, argv);
896     if( auto_run )
897         Fl::add_timeout( 0.1, cb_AutoRun, aviname_left );
898     Fl::run();
899     cb_Exit(0,0);
900     return 0;
901 }
902 #endif