use full word "display" for variable in all places
[ozzloy@gmail.com/oble] / oble.cpp
index fcba87c697cf05f7061bc12909072f40c5a94459..be973e23c11704828e781a483c420365b2fd91c8 100644 (file)
--- a/oble.cpp
+++ b/oble.cpp
@@ -1,37 +1,20 @@
 //use the camera to aid the decision to sleep.
 //Copyright 2009 Daniel Watson
 /*
-    use a camera to prevent screensaver
-    Copyright (C) 2009  daniel watson, ozzloy@gmail.com
+  This file is part of oble.
 
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
+  oble is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
 
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
+  oble is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
 
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-/*
-        This file is part of oble.
-
-        oble is free software: you can redistribute it and/or modify
-        it under the terms of the GNU General Public License as published by
-        the Free Software Foundation, either version 3 of the License, or
-        (at your option) any later version.
-
-        oble is distributed in the hope that it will be useful,
-        but WITHOUT ANY WARRANTY; without even the implied warranty of
-        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-        GNU General Public License for more details.
-
-        You should have received a copy of the GNU General Public License
-        along with oble.  If not, see <http://www.gnu.org/licenses/>.
+  You should have received a copy of the GNU General Public License
+  along with oble.  If not, see <http://www.gnu.org/licenses/>.
 
 */
 #include <cv.h>
@@ -53,200 +36,239 @@ static int verbose = 0;
 
 CvHaarClassifierCascade* load_object_detector(const char* cascade_path)
 {
-       return (CvHaarClassifierCascade*)cvLoad(cascade_path);
+  return (CvHaarClassifierCascade*)cvLoad(cascade_path);
 }
 
 void detect_and_draw_objects(IplImage* image,
-               CvHaarClassifierCascade* cascade,
-               int do_pyramids)
+                            CvHaarClassifierCascade* cascade,
+                            int do_pyramids)
 {
-       IplImage* small_image = image;
-       CvMemStorage* storage = cvCreateMemStorage(0);
-       CvSeq* faces;
-       int i, scale = 1;
-       static int saw_last_time = 0;
-
-       /* if the flag is specified, down-scale the input image to get a
-                performance boost w/o loosing quality (perhaps) */
-       if(do_pyramids)
-       {
-               small_image = cvCreateImage(cvSize(image->width/2,image->height/2),
-                               IPL_DEPTH_8U, 3);
-               cvPyrDown(image, small_image, CV_GAUSSIAN_5x5);
-               scale = 2;
-       }
+  IplImage* small_image = image;
+  CvMemStorage* storage = cvCreateMemStorage(0);
+  CvSeq* faces;
+  int i, scale = 1;
+
+  /* if the flag is specified, down-scale the input image to get a
+     performance boost w/o loosing quality (perhaps) */
+  if(do_pyramids)
+    {
+      small_image = cvCreateImage(cvSize(image->width/2,
+                                        image->height/2),
+                                 IPL_DEPTH_8U, 3);
+      cvPyrDown(image, small_image, CV_GAUSSIAN_5x5);
+      scale = 2;
+    }
+
+  /* use the fastest variant */
+  faces = cvHaarDetectObjects(small_image, cascade, storage, 1.2, 2,
+                             CV_HAAR_DO_CANNY_PRUNING);
 
-       /* use the fastest variant */
-       faces = cvHaarDetectObjects(small_image, cascade, storage, 1.2, 2,
-                       CV_HAAR_DO_CANNY_PRUNING);
+  update_idle(faces->total);
 
-       if(0 < faces->total)
+  /* draw all the rectangles */
+  for(i = 0; i < faces->total; i++)
+    {
+      /* extract the rectangles only */
+      CvRect face = *(CvRect*)cvGetSeqElem(faces, i);
+      CvPoint upperLeft = cvPoint(face.x * scale, face.y * scale);
+      CvPoint bottomRight = cvPoint((face.x + face.width) * scale,
+                                   (face.y + face.height) * scale);
+      cvRectangle(image, upperLeft, bottomRight, CV_RGB(255,0,0), 3);
+    }
+
+  if(small_image != image)
+    cvReleaseImage(&small_image);
+  cvReleaseMemStorage(&storage);
+}
+
+void update_idle(int faces_total)
+{
+  static int saw_last_time = 0;
+
+  if(0 < faces_total)
+    {
+      t_current = time(NULL);
+      if(verbose)
        {
-               t_current = time(NULL);
-               if(verbose)
-               {
-                       printf(":) face \n");
-               }
-               if(saw_last_time)
-               {
-                       if(verbose)printf("\t\tpoking\n");
-                       reset_idle_time();
-                       system("gnome-screensaver-command --poke");
-               }
-               saw_last_time = 1;
+         printf(":) face \n");
        }
-       else
+      if(saw_last_time)
        {
-               saw_last_time = 0;
-               if(verbose)
-               {
-                       printf(":( no face \n");
-               }
+         if(verbose)printf("\t\tpoking\n");
+         reset_idle_time();
        }
-
-       /* draw all the rectangles */
-       for(i = 0; i < faces->total; i++)
+      saw_last_time = 1;
+    }
+  else
+    {
+      saw_last_time = 0;
+      if(verbose)
        {
-               /* extract the rectangles only */
-               CvRect face = *(CvRect*)cvGetSeqElem(faces, i);
-               CvPoint upperLeft = cvPoint(face.x * scale, face.y * scale);
-               CvPoint bottomRight = cvPoint((face.x + face.width) * scale,
-                               (face.y + face.height) * scale);
-               cvRectangle(image, upperLeft, bottomRight, CV_RGB(255,0,0), 3);
+         printf(":( no face \n");
        }
+    }
 
-       if(small_image != image)
-               cvReleaseImage(&small_image);
-       cvReleaseMemStorage(&storage);
 }
 
 void screensave(time_t t_current)
 {
-       static int last_elapse = 0;
-       static int activated = 0;
-       int elapse = difftime(time(NULL), t_current);
-       int timeout = 10;
-       if(elapse > timeout && elapse != last_elapse)
+  static int last_elapse = 0;
+  static int activated = 0;
+  int elapse = difftime(time(NULL), t_current);
+  int timeout = 10;
+  if(elapse > timeout && elapse != last_elapse)
+    {
+      last_elapse = elapse;
+      if(verbose)
        {
-               last_elapse = elapse;
-               if(verbose)
-               {
-                       printf("elapse = %d\n", elapse);
-               }
-               if(!activated)
-               {
-                       printf("activated\n");
-                       activated = 1;
-                       system("gnome-screensaver-command -a");
-               }
+         printf("elapse = %d\n", elapse);
        }
-       if(elapse < timeout && activated)
+      if(!activated)
        {
-               printf("deactivated\n");
-               activated = 0;
-               system("gnome-screensaver-command -d");
+         printf("activated\n");
+         activated = 1;
+         system("gnome-screensaver-command -a");
        }
+    }
+  if(elapse < timeout && activated)
+    {
+      printf("deactivated\n");
+      activated = 0;
+      system("gnome-screensaver-command -d");
+    }
 }
 
 int parse_opts(int argc, char **argv)
 {
-       int index, c;
-       opterr = 0;
-       const char *options = "vc:";
-       while((c = getopt(argc, argv, options)) != -1)
+  int index, c;
+  opterr = 0;
+  const char *options = "vc:\x0";
+  while((c = getopt(argc, argv, options)) != -1)
+    {
+      switch(c)
        {
-               switch(c)
-               {
-                       case 'v': verbose = 1; break;
-                       case 'c': cascade_filename = string(optarg); break;
-                       case '?':
-                               if(optopt == 'c')
-                               {
-                                       printf("option -%c requires an argument.\n", optopt);
-                               }
-                               else if(isprint (optopt))
-                               {
-                                       printf("unknown option `-%c'.\n", optopt);
-                               }
-                               else
-                               {
-                                       printf("unknown option char `\\x%x'.\n", optopt);
-                               }
-                               break;
-                       default: abort();
-               }
+       case 'v': verbose = 1; break;
+       case 'c': cascade_filename = string(optarg); break;
+       case '?':
+         if(optopt == 'c')
+           {
+             printf("option -%c requires an argument.\n", optopt);
+           }
+         else if(isprint (optopt))
+           {
+             printf("unknown option `-%c'.\n", optopt);
+           }
+         else
+           {
+             printf("unknown option char `\\x%x'.\n", optopt);
+           }
+         break;
+       case '\x0': break; //ignore.  not sure why this shows up.  maybe zsh?
+       default: abort();
        }
+    }
 
-       for(index = optind; index < argc; index++)
-               printf("Non-option arg %s\n", argv[index]);
+  for(index = optind; index < argc; index++)
+    printf("Non-option arg %s\n", argv[index]);
 
-       if(cascade_filename == "")
-       {
-               printf("you must supply a filename with -c option.  example:\n");
-               printf(
-                               "%s -c %s\n",
-                               argv[0],
-                               "/usr/share/opencv/haarcascades/haarcascade_frontalface_alt.xml"
-                               );
-               return 1;
-       }
-       if(verbose) printf("SILENT ALARM ACTIVATED!!!\n");
-       return 0;
+  if(cascade_filename == "")
+    {
+      printf("you must supply a filename with -c option.  example:\n");
+      printf(
+            "%s -c %s\n",
+            argv[0],
+            "/usr/share/opencv/haarcascades/haarcascade_frontalface_alt.xml"
+            );
+      return 1;
+    }
+  if(verbose) printf("SILENT ALARM ACTIVATED!!!\n");
+  return 0;
 }
 
-// A Simple Camera Capture Framework.
-int main(int argc, char** argv)
+int get_frames(CvCapture* capture, CvHaarClassifierCascade* cascade)
 {
-       if(parse_opts(argc, argv)) return 0;
+  int got_null_frame = 0;
+  IplImage* frame = NULL;
+  get_one_frame(capture, frame);
 
-       CvHaarClassifierCascade* cascade =
-               load_object_detector(cascade_filename.c_str());
+  IplImage* mirrored =
+    cvCreateImage(cvGetSize(frame), frame->depth, frame->nChannels);
+  // Show the image captured from the camera in the window and repeat
+  while(!(got_null_frame = get_one_frame(capture, frame)))
+    {
+      //so displayed right/left corresponds to physical right/left:
+      cvFlip(frame, mirrored, MIRROR);
 
-       CvCapture* capture = cvCaptureFromCAM(CV_CAP_ANY);
-       if(!capture) {
-               cerr << "ERROR: capture is NULL " << endl;
-               getchar();
-               return -1;
-       }
+      detect_and_draw_objects(mirrored, cascade, 1);
+      cvShowImage("mywindow", mirrored);
+      // Do not release the frame!
+      //screensave(t_current);
 
-       // Create a window in which the captured images will be presented
-       cvNamedWindow("mywindow", CV_WINDOW_AUTOSIZE);
+      //If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version),
+      //remove higher bits using AND operator
+      if((cvWaitKey(100) & 255) == 27) break;
+    }
+  cvReleaseImage(&mirrored);
+  return got_null_frame;
+}
 
-       IplImage* frame = cvQueryFrame(capture);
-       if(!frame) {
-               cerr << "ERROR: frame is null..." << endl;
-               getchar();
-               return -1;
-       }
-       IplImage* mirrored =
-               cvCreateImage(cvGetSize(frame), frame->depth, frame->nChannels);
-       t_current = time(NULL);
-       // Show the image captured from the camera in the window and repeat
-       while(1) {
-               // Get one frame
-               frame = cvQueryFrame(capture);
-               if(!frame) {
-                       cerr << "ERROR: frame is null..." << endl;
-                       getchar();
-                       break;
-               }
-
-               //flip the image so displayed right/left corresponds to physical right/left
-               cvFlip(frame, mirrored, MIRROR);
-
-               detect_and_draw_objects(mirrored, cascade, 1);
-               cvShowImage("mywindow", mirrored);
-               // Do not release the frame!
-               //screensave(t_current);
-
-               //If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version),
-               //remove higher bits using AND operator
-               if((cvWaitKey(100) & 255) == 27) break;
-       }
+int do_capture()
+{
+  int got_null_capture = 0;
+  CvHaarClassifierCascade* cascade =
+    load_object_detector(cascade_filename.c_str());
+
+  CvCapture* capture = cvCaptureFromCAM(CV_CAP_ANY);
+  if(!capture) {
+    cerr << "ERROR: capture is NULL " << endl;
+    return 1;
+  }
+
+  // Create a window in which the captured images will be presented
+  cvNamedWindow("mywindow", CV_WINDOW_AUTOSIZE);
+  t_current = time(NULL);
+  while(get_frames(capture, cascade))
+    {
+      cerr << "resetting capture." << endl;
+      cvReleaseCapture( &capture );
+      capture = cvCaptureFromCAM( CV_CAP_ANY );
+      if(!capture)
+        {
+          got_null_capture = 1;
+          break;
+        }
+    }
+
+  // Release the capture device housekeeping
+  if(!got_null_capture)
+    {
+      cvReleaseCapture(&capture);
+    }
+  cvDestroyWindow("mywindow");
+  return got_null_capture;
+}
+
+int get_one_frame(CvCapture* capture, IplImage* &frame)
+{
+  int got_null_frame = 0;
+  frame = cvQueryFrame(capture);
+  if(!frame)
+    {
+      cerr << "ERROR: frame is null..., trying again" << endl;
+      frame = cvQueryFrame(capture); 
+      if(!frame)
+        {
+          cerr << "ERROR: frame is still null... maybe reset capture?" << endl;
+          got_null_frame = 1;
+        }
+    }
+  return got_null_frame;
+}
+
+// A Simple Camera Capture Framework.
+int main(int argc, char** argv)
+{
+  if(parse_opts(argc, argv)) return 0;
 
-       // Release the capture device housekeeping
-       cvReleaseCapture(&capture);
-       cvDestroyWindow("mywindow");
-       cvReleaseImage(&mirrored);
-       return 0;
+  return do_capture();
 }