cpp indented via emacs
[ozzloy@gmail.com/oble] / oble.cpp
1 //use the camera to aid the decision to sleep.
2 //Copyright 2009 Daniel Watson
3 /*
4 This file is part of oble.
5
6 oble is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 oble is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with oble. If not, see <http://www.gnu.org/licenses/>.
18
19 */
20 #include <cv.h>
21 #include <highgui.h>
22 #include <stdio.h>
23 #include <iostream>
24 #include <time.h>
25 #include <unistd.h>
26 #include "oble.h"
27 #include "idle_x11.h"
28
29 using namespace std;
30
31 static string cascade_filename = "";
32 static int verbose = 0;
33
34 // argument for cvFlip(src, dest, FLIP_TYPE)
35 #define MIRROR 1
36
37 CvHaarClassifierCascade* load_object_detector(const char* cascade_path)
38 {
39 return (CvHaarClassifierCascade*)cvLoad(cascade_path);
40 }
41
42 void detect_and_draw_objects(IplImage* image,
43 CvHaarClassifierCascade* cascade,
44 int do_pyramids)
45 {
46 IplImage* small_image = image;
47 CvMemStorage* storage = cvCreateMemStorage(0);
48 CvSeq* faces;
49 int i, scale = 1;
50
51 /* if the flag is specified, down-scale the input image to get a
52 performance boost w/o loosing quality (perhaps) */
53 if(do_pyramids)
54 {
55 small_image = cvCreateImage(cvSize(image->width/2,
56 image->height/2),
57 IPL_DEPTH_8U, 3);
58 cvPyrDown(image, small_image, CV_GAUSSIAN_5x5);
59 scale = 2;
60 }
61
62 /* use the fastest variant */
63 faces = cvHaarDetectObjects(small_image, cascade, storage, 1.2, 2,
64 CV_HAAR_DO_CANNY_PRUNING);
65
66 update_idle(faces->total);
67
68 /* draw all the rectangles */
69 for(i = 0; i < faces->total; i++)
70 {
71 /* extract the rectangles only */
72 CvRect face = *(CvRect*)cvGetSeqElem(faces, i);
73 CvPoint upperLeft = cvPoint(face.x * scale, face.y * scale);
74 CvPoint bottomRight = cvPoint((face.x + face.width) * scale,
75 (face.y + face.height) * scale);
76 cvRectangle(image, upperLeft, bottomRight, CV_RGB(255,0,0), 3);
77 }
78
79 if(small_image != image)
80 cvReleaseImage(&small_image);
81 cvReleaseMemStorage(&storage);
82 }
83
84 void update_idle(int faces_total)
85 {
86 static int saw_last_time = 0;
87
88 if(0 < faces_total)
89 {
90 t_current = time(NULL);
91 if(verbose)
92 {
93 printf(":) face \n");
94 }
95 if(saw_last_time)
96 {
97 if(verbose)printf("\t\tpoking\n");
98 reset_idle_time();
99 system("gnome-screensaver-command --poke");
100 }
101 saw_last_time = 1;
102 }
103 else
104 {
105 saw_last_time = 0;
106 if(verbose)
107 {
108 printf(":( no face \n");
109 }
110 }
111
112 }
113
114 void screensave(time_t t_current)
115 {
116 static int last_elapse = 0;
117 static int activated = 0;
118 int elapse = difftime(time(NULL), t_current);
119 int timeout = 10;
120 if(elapse > timeout && elapse != last_elapse)
121 {
122 last_elapse = elapse;
123 if(verbose)
124 {
125 printf("elapse = %d\n", elapse);
126 }
127 if(!activated)
128 {
129 printf("activated\n");
130 activated = 1;
131 system("gnome-screensaver-command -a");
132 }
133 }
134 if(elapse < timeout && activated)
135 {
136 printf("deactivated\n");
137 activated = 0;
138 system("gnome-screensaver-command -d");
139 }
140 }
141
142 int parse_opts(int argc, char **argv)
143 {
144 int index, c;
145 opterr = 0;
146 const char *options = "vc:\x0";
147 while((c = getopt(argc, argv, options)) != -1)
148 {
149 switch(c)
150 {
151 case 'v': verbose = 1; break;
152 case 'c': cascade_filename = string(optarg); break;
153 case '?':
154 if(optopt == 'c')
155 {
156 printf("option -%c requires an argument.\n", optopt);
157 }
158 else if(isprint (optopt))
159 {
160 printf("unknown option `-%c'.\n", optopt);
161 }
162 else
163 {
164 printf("unknown option char `\\x%x'.\n", optopt);
165 }
166 break;
167 case '\x0': break; //ignore. not sure why this shows up. maybe zsh?
168 default: abort();
169 }
170 }
171
172 for(index = optind; index < argc; index++)
173 printf("Non-option arg %s\n", argv[index]);
174
175 if(cascade_filename == "")
176 {
177 printf("you must supply a filename with -c option. example:\n");
178 printf(
179 "%s -c %s\n",
180 argv[0],
181 "/usr/share/opencv/haarcascades/haarcascade_frontalface_alt.xml"
182 );
183 return 1;
184 }
185 if(verbose) printf("SILENT ALARM ACTIVATED!!!\n");
186 return 0;
187 }
188
189 void get_frames(CvCapture* capture, CvHaarClassifierCascade* cascade)
190 {
191 IplImage* frame = NULL;
192 get_one_frame(capture, frame);
193
194 IplImage* mirrored =
195 cvCreateImage(cvGetSize(frame), frame->depth, frame->nChannels);
196 // Show the image captured from the camera in the window and repeat
197 while(1) {
198 if(get_one_frame(capture, frame)) break;
199
200 //flip the image so displayed right/left corresponds to physical right/left
201 cvFlip(frame, mirrored, MIRROR);
202
203 detect_and_draw_objects(mirrored, cascade, 1);
204 cvShowImage("mywindow", mirrored);
205 // Do not release the frame!
206 //screensave(t_current);
207
208 //If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version),
209 //remove higher bits using AND operator
210 if((cvWaitKey(100) & 255) == 27) break;
211 }
212 cvReleaseImage(&mirrored);
213 }
214
215 int do_capture()
216 {
217 CvHaarClassifierCascade* cascade =
218 load_object_detector(cascade_filename.c_str());
219
220 CvCapture* capture = cvCaptureFromCAM(CV_CAP_ANY);
221 if(!capture) {
222 cerr << "ERROR: capture is NULL " << endl;
223 getchar();
224 return -1;
225 }
226
227 // Create a window in which the captured images will be presented
228 cvNamedWindow("mywindow", CV_WINDOW_AUTOSIZE);
229 t_current = time(NULL);
230 get_frames(capture, cascade);
231
232 // Release the capture device housekeeping
233 cvReleaseCapture(&capture);
234 cvDestroyWindow("mywindow");
235 return 0;
236 }
237
238 int get_one_frame(CvCapture* capture, IplImage* &frame)
239 {
240 frame = cvQueryFrame(capture);
241 if(!frame) {
242 cerr << "ERROR: frame is null..." << endl;
243 getchar();
244 return 1;
245 }
246 return 0;
247 }
248
249 // A Simple Camera Capture Framework.
250 int main(int argc, char** argv)
251 {
252 if(parse_opts(argc, argv)) return 0;
253
254 return do_capture();
255 }