allow specifying cascade file as cli arg. Closes #7
[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/*
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*/
a92408ab 20/*
4d640880 21 This file is part of oble.
a92408ab 22
4d640880 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.
a92408ab 27
4d640880 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.
a92408ab 32
4d640880 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/>.
a92408ab 35
4d640880 36*/
b7e484d5 37#include <cv.h>
38#include <highgui.h>
39#include <stdio.h>
4d640880 40#include <iostream>
e0c48375 41#include <time.h>
5a96bc78 42#include <unistd.h>
124727d2 43#include "oble.h"
4f219a9f 44#include "idle_x11.h"
b8b01547 45
e0c48375 46using namespace std;
b7e484d5 47
5a96bc78 48static string cascade_filename = "";
49
0d6b136c 50// argument for cvFlip(src, dest, FLIP_TYPE)
4d640880 51#define MIRROR 1
0d6b136c 52
4f219a9f 53#define DEBUG 0
54
64fb0216 55CvHaarClassifierCascade* load_object_detector(const char* cascade_path)
b7e484d5 56{
21323a92 57 return (CvHaarClassifierCascade*)cvLoad(cascade_path);
b7e484d5 58}
59
9cd4e78c 60void detect_and_draw_objects(IplImage* image,
b7e484d5 61 CvHaarClassifierCascade* cascade,
9cd4e78c 62 int do_pyramids)
b7e484d5 63{
64 IplImage* small_image = image;
65 CvMemStorage* storage = cvCreateMemStorage(0);
66 CvSeq* faces;
67 int i, scale = 1;
4f219a9f 68 static int saw_last_time = 0;
b7e484d5 69
70 /* if the flag is specified, down-scale the input image to get a
71 performance boost w/o loosing quality (perhaps) */
21323a92 72 if(do_pyramids)
b7e484d5 73 {
21323a92 74 small_image = cvCreateImage(cvSize(image->width/2,image->height/2),
75 IPL_DEPTH_8U, 3);
76 cvPyrDown(image, small_image, CV_GAUSSIAN_5x5);
b7e484d5 77 scale = 2;
78 }
79
80 /* use the fastest variant */
21323a92 81 faces = cvHaarDetectObjects(small_image, cascade, storage, 1.2, 2,
82 CV_HAAR_DO_CANNY_PRUNING);
b7e484d5 83
4d640880 84 if(0 < faces->total)
b8b01547 85 {
e0c48375 86 t_current = time(NULL);
4f219a9f 87 if(DEBUG)
88 {
89 printf(":) face \n");
90 }
91 if(saw_last_time)
92 {
93 if(DEBUG)printf("\t\tpoking\n");
94 reset_idle_time();
95 system("gnome-screensaver-command --poke");
96 }
97 saw_last_time = 1;
98 }
99 else
100 {
101 saw_last_time = 0;
102 if(DEBUG)
103 {
104 printf(":( no face \n");
105 }
b8b01547 106 }
b8b01547 107
b7e484d5 108 /* draw all the rectangles */
21323a92 109 for(i = 0; i < faces->total; i++)
b7e484d5 110 {
111 /* extract the rectangles only */
21323a92 112 CvRect face = *(CvRect*)cvGetSeqElem(faces, i);
79292335 113 CvPoint upperLeft = cvPoint(face.x * scale, face.y * scale);
114 CvPoint bottomRight = cvPoint((face.x + face.width) * scale,
115 (face.y + face.height) * scale);
21323a92 116 cvRectangle(image, upperLeft, bottomRight, CV_RGB(255,0,0), 3);
b7e484d5 117 }
118
21323a92 119 if(small_image != image)
120 cvReleaseImage(&small_image);
121 cvReleaseMemStorage(&storage);
b7e484d5 122}
123
e0c48375 124void screensave(time_t t_current)
b7e484d5 125{
e0c48375 126 static int last_elapse = 0;
127 static int activated = 0;
128 int elapse = difftime(time(NULL), t_current);
129 int timeout = 10;
130 if(elapse > timeout && elapse != last_elapse)
b8b01547 131 {
e0c48375 132 last_elapse = elapse;
4f219a9f 133 if(DEBUG)
134 {
135 printf("elapse = %d\n", elapse);
136 }
e0c48375 137 if(!activated)
138 {
139 printf("activated\n");
140 activated = 1;
141 system("gnome-screensaver-command -a");
142 }
143 }
144 if(elapse < timeout && activated)
145 {
146 printf("deactivated\n");
147 activated = 0;
148 system("gnome-screensaver-command -d");
149 }
150}
b8b01547 151
5a96bc78 152int parse_opts(int argc, char **argv)
153{
154 int index, c;
155 //int opterr=0, optopt=0, optind=0;
156 //char *optarg;
157 // int getopt(int argc, char **argv, const char *options);
158 opterr = 0;
159 const char *options = "c:";
160 while((c = getopt(argc, argv, options)) != -1)
161 switch(c)
162 {
163 case 'c':
164 cascade_filename = string(optarg);
165 printf("option c, argument = %s\n", optarg);
166 case '?':
167 if(optopt == 'c')
168 printf("option -%c requires an argument.\n", optopt);
169 else if(isprint (optopt))
170 printf("unknown option `-%c'.\n", optopt);
171 else
172 printf("unknown option char `\\x%x'.\n", optopt);
173 goto known_args_processed;
174 default:
175 abort();
176 }
177known_args_processed:
178
179 for(index = optind; index < argc; index++)
180 printf("Non-option arg %s\n", argv[index]);
181
182 return 0;
183}
184
e0c48375 185// A Simple Camera Capture Framework.
186int main(int argc, char** argv)
187{
5a96bc78 188 if(parse_opts(argc, argv)) return 0;
189
190 if(cascade_filename == "") cascade_filename = string(argv[1]);
191 CvHaarClassifierCascade* cascade =
192 load_object_detector(cascade_filename.c_str());
b7e484d5 193
21323a92 194 CvCapture* capture = cvCaptureFromCAM(CV_CAP_ANY);
195 if(!capture) {
4d640880 196 cerr << "ERROR: capture is NULL " << endl;
b7e484d5 197 getchar();
198 return -1;
199 }
200
201 // Create a window in which the captured images will be presented
21323a92 202 cvNamedWindow("mywindow", CV_WINDOW_AUTOSIZE);
b7e484d5 203
0d6b136c 204 IplImage* frame = cvQueryFrame(capture);
205 if(!frame) {
4d640880 206 cerr << "ERROR: frame is null..." << endl;
0d6b136c 207 getchar();
208 return -1;
209 }
b8b01547 210 IplImage* mirrored =
0d6b136c 211 cvCreateImage(cvGetSize(frame), frame->depth, frame->nChannels);
e0c48375 212 t_current = time(NULL);
b7e484d5 213 // Show the image captured from the camera in the window and repeat
21323a92 214 while(1) {
b7e484d5 215 // Get one frame
0d6b136c 216 frame = cvQueryFrame(capture);
21323a92 217 if(!frame) {
4d640880 218 cerr << "ERROR: frame is null..." << endl;
b7e484d5 219 getchar();
220 break;
221 }
222
21323a92 223 //flip the image so displayed right/left corresponds to physical right/left
4d640880 224 cvFlip(frame, mirrored, MIRROR);
64fb0216 225
b8b01547 226 detect_and_draw_objects(mirrored, cascade, 1);
227 cvShowImage("mywindow", mirrored);
b7e484d5 228 // Do not release the frame!
4f219a9f 229 //screensave(t_current);
b7e484d5 230
231 //If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version),
232 //remove higher bits using AND operator
e0c48375 233 if((cvWaitKey(100) & 255) == 27) break;
b7e484d5 234 }
235
236 // Release the capture device housekeeping
21323a92 237 cvReleaseCapture(&capture);
238 cvDestroyWindow("mywindow");
b8b01547 239 cvReleaseImage(&mirrored);
b7e484d5 240 return 0;
241}