use full word "display" for variable in all places
[ozzloy@gmail.com/oble] / oble.cpp
CommitLineData
a92408ab 1//use the camera to aid the decision to sleep.
2//Copyright 2009 Daniel Watson
ccb0e7df 3/*
3347b0aa 4 This file is part of oble.
ccb0e7df 5
3347b0aa 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.
ccb0e7df 10
3347b0aa 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.
ccb0e7df 15
3347b0aa 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/>.
a92408ab 18
4d640880 19*/
b7e484d5 20#include <cv.h>
21#include <highgui.h>
22#include <stdio.h>
4d640880 23#include <iostream>
e0c48375 24#include <time.h>
5a96bc78 25#include <unistd.h>
124727d2 26#include "oble.h"
4f219a9f 27#include "idle_x11.h"
b8b01547 28
e0c48375 29using namespace std;
b7e484d5 30
5a96bc78 31static string cascade_filename = "";
2b11aff4 32static int verbose = 0;
5a96bc78 33
0d6b136c 34// argument for cvFlip(src, dest, FLIP_TYPE)
4d640880 35#define MIRROR 1
0d6b136c 36
64fb0216 37CvHaarClassifierCascade* load_object_detector(const char* cascade_path)
b7e484d5 38{
3347b0aa 39 return (CvHaarClassifierCascade*)cvLoad(cascade_path);
b7e484d5 40}
41
9cd4e78c 42void detect_and_draw_objects(IplImage* image,
3347b0aa 43 CvHaarClassifierCascade* cascade,
44 int do_pyramids)
b7e484d5 45{
3347b0aa 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);
12af27da 82}
83
84void update_idle(int faces_total)
85{
3347b0aa 86 static int saw_last_time = 0;
12af27da 87
3347b0aa 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)
b8b01547 96 {
3347b0aa 97 if(verbose)printf("\t\tpoking\n");
98 reset_idle_time();
4f219a9f 99 }
3347b0aa 100 saw_last_time = 1;
101 }
102 else
103 {
104 saw_last_time = 0;
105 if(verbose)
4f219a9f 106 {
3347b0aa 107 printf(":( no face \n");
b8b01547 108 }
3347b0aa 109 }
b8b01547 110
b7e484d5 111}
112
e0c48375 113void screensave(time_t t_current)
b7e484d5 114{
3347b0aa 115 static int last_elapse = 0;
116 static int activated = 0;
117 int elapse = difftime(time(NULL), t_current);
118 int timeout = 10;
119 if(elapse > timeout && elapse != last_elapse)
120 {
121 last_elapse = elapse;
122 if(verbose)
b8b01547 123 {
3347b0aa 124 printf("elapse = %d\n", elapse);
e0c48375 125 }
3347b0aa 126 if(!activated)
e0c48375 127 {
3347b0aa 128 printf("activated\n");
129 activated = 1;
130 system("gnome-screensaver-command -a");
e0c48375 131 }
3347b0aa 132 }
133 if(elapse < timeout && activated)
134 {
135 printf("deactivated\n");
136 activated = 0;
137 system("gnome-screensaver-command -d");
138 }
e0c48375 139}
b8b01547 140
5a96bc78 141int parse_opts(int argc, char **argv)
142{
3347b0aa 143 int index, c;
144 opterr = 0;
145 const char *options = "vc:\x0";
146 while((c = getopt(argc, argv, options)) != -1)
147 {
148 switch(c)
2b11aff4 149 {
3347b0aa 150 case 'v': verbose = 1; break;
151 case 'c': cascade_filename = string(optarg); break;
152 case '?':
153 if(optopt == 'c')
154 {
155 printf("option -%c requires an argument.\n", optopt);
156 }
157 else if(isprint (optopt))
158 {
159 printf("unknown option `-%c'.\n", optopt);
160 }
161 else
162 {
163 printf("unknown option char `\\x%x'.\n", optopt);
164 }
165 break;
166 case '\x0': break; //ignore. not sure why this shows up. maybe zsh?
167 default: abort();
2b11aff4 168 }
3347b0aa 169 }
170
171 for(index = optind; index < argc; index++)
172 printf("Non-option arg %s\n", argv[index]);
173
174 if(cascade_filename == "")
175 {
176 printf("you must supply a filename with -c option. example:\n");
177 printf(
178 "%s -c %s\n",
179 argv[0],
180 "/usr/share/opencv/haarcascades/haarcascade_frontalface_alt.xml"
181 );
182 return 1;
183 }
184 if(verbose) printf("SILENT ALARM ACTIVATED!!!\n");
185 return 0;
5a96bc78 186}
187
9618584c 188int get_frames(CvCapture* capture, CvHaarClassifierCascade* cascade)
e0c48375 189{
9618584c 190 int got_null_frame = 0;
3347b0aa 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
9618584c 197 while(!(got_null_frame = get_one_frame(capture, frame)))
198 {
199 //so displayed right/left corresponds to physical right/left:
200 cvFlip(frame, mirrored, MIRROR);
3347b0aa 201
9618584c 202 detect_and_draw_objects(mirrored, cascade, 1);
203 cvShowImage("mywindow", mirrored);
204 // Do not release the frame!
205 //screensave(t_current);
3347b0aa 206
9618584c 207 //If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version),
208 //remove higher bits using AND operator
209 if((cvWaitKey(100) & 255) == 27) break;
210 }
3347b0aa 211 cvReleaseImage(&mirrored);
9618584c 212 return got_null_frame;
12af27da 213}
214
215int do_capture()
216{
9618584c 217 int got_null_capture = 0;
3347b0aa 218 CvHaarClassifierCascade* cascade =
219 load_object_detector(cascade_filename.c_str());
220
221 CvCapture* capture = cvCaptureFromCAM(CV_CAP_ANY);
222 if(!capture) {
223 cerr << "ERROR: capture is NULL " << endl;
9618584c 224 return 1;
3347b0aa 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);
9618584c 230 while(get_frames(capture, cascade))
231 {
232 cerr << "resetting capture." << endl;
233 cvReleaseCapture( &capture );
234 capture = cvCaptureFromCAM( CV_CAP_ANY );
235 if(!capture)
236 {
237 got_null_capture = 1;
238 break;
239 }
240 }
3347b0aa 241
242 // Release the capture device housekeeping
9618584c 243 if(!got_null_capture)
244 {
245 cvReleaseCapture(&capture);
246 }
3347b0aa 247 cvDestroyWindow("mywindow");
9618584c 248 return got_null_capture;
b7e484d5 249}
12af27da 250
251int get_one_frame(CvCapture* capture, IplImage* &frame)
252{
9618584c 253 int got_null_frame = 0;
3347b0aa 254 frame = cvQueryFrame(capture);
9618584c 255 if(!frame)
256 {
257 cerr << "ERROR: frame is null..., trying again" << endl;
8e301183 258 frame = cvQueryFrame(capture);
9618584c 259 if(!frame)
260 {
261 cerr << "ERROR: frame is still null... maybe reset capture?" << endl;
262 got_null_frame = 1;
263 }
264 }
265 return got_null_frame;
12af27da 266}
267
268// A Simple Camera Capture Framework.
269int main(int argc, char** argv)
270{
3347b0aa 271 if(parse_opts(argc, argv)) return 0;
12af27da 272
3347b0aa 273 return do_capture();
12af27da 274}