cpp indented via emacs
[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();
99 system("gnome-screensaver-command --poke");
4f219a9f 100 }
3347b0aa 101 saw_last_time = 1;
102 }
103 else
104 {
105 saw_last_time = 0;
106 if(verbose)
4f219a9f 107 {
3347b0aa 108 printf(":( no face \n");
b8b01547 109 }
3347b0aa 110 }
b8b01547 111
b7e484d5 112}
113
e0c48375 114void screensave(time_t t_current)
b7e484d5 115{
3347b0aa 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)
b8b01547 124 {
3347b0aa 125 printf("elapse = %d\n", elapse);
e0c48375 126 }
3347b0aa 127 if(!activated)
e0c48375 128 {
3347b0aa 129 printf("activated\n");
130 activated = 1;
131 system("gnome-screensaver-command -a");
e0c48375 132 }
3347b0aa 133 }
134 if(elapse < timeout && activated)
135 {
136 printf("deactivated\n");
137 activated = 0;
138 system("gnome-screensaver-command -d");
139 }
e0c48375 140}
b8b01547 141
5a96bc78 142int parse_opts(int argc, char **argv)
143{
3347b0aa 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)
2b11aff4 150 {
3347b0aa 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();
2b11aff4 169 }
3347b0aa 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;
5a96bc78 187}
188
12af27da 189void get_frames(CvCapture* capture, CvHaarClassifierCascade* cascade)
e0c48375 190{
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
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);
12af27da 213}
214
215int do_capture()
216{
3347b0aa 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;
b7e484d5 236}
12af27da 237
238int get_one_frame(CvCapture* capture, IplImage* &frame)
239{
3347b0aa 240 frame = cvQueryFrame(capture);
241 if(!frame) {
242 cerr << "ERROR: frame is null..." << endl;
243 getchar();
244 return 1;
245 }
246 return 0;
12af27da 247}
248
249// A Simple Camera Capture Framework.
250int main(int argc, char** argv)
251{
3347b0aa 252 if(parse_opts(argc, argv)) return 0;
12af27da 253
3347b0aa 254 return do_capture();
12af27da 255}