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