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