From 4f219a9f3ebe898145cce69ce2ecf8ce3366a4fd Mon Sep 17 00:00:00 2001 From: ozzloy Date: Thu, 18 Feb 2010 00:55:31 -0800 Subject: [PATCH] face detection resets idle time and deactivates ss --- Makefile | 15 ++++-- NOTES | 10 ---- TODO | 21 ++------- idle_x11.cpp | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++ idle_x11.h | 3 ++ oble.cpp | 31 ++++++++++-- 6 files changed, 178 insertions(+), 32 deletions(-) create mode 100644 idle_x11.cpp create mode 100644 idle_x11.h diff --git a/Makefile b/Makefile index 7391fbd..e268f88 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,23 @@ all: oble -oble: oble.cpp oble.h - gcc `pkg-config --cflags opencv` -o oble oble.cpp `pkg-config --libs opencv` +PKGS = opencv x11 xext xscrnsaver +CXXFLAGS += $(shell pkg-config --cflags $(PKGS)) +LDFLAGS += $(shell pkg-config --libs $(PKGS)) + +OBJS = idle_x11.o oble.o + +idle_x11.o: idle_x11.h +oble.o: oble.h + +oble: $(OBJS) + gcc $(LDFLAGS) -o $@ $(OBJS) test: all ./oble /usr/share/opencv/haarcascades/haarcascade_frontalface_alt.xml clean: - rm -rf oble + rm -rf oble *.o new: clean all diff --git a/NOTES b/NOTES index 7554836..e69de29 100644 --- a/NOTES +++ b/NOTES @@ -1,10 +0,0 @@ -(screensaver activation and deactivation) has 2 managers right now. oble and -gnome-screensaver have independent criteria for activation and deactivation. -oble relies only on time since face detected, gss relies on time since keyboard -or mouse state change. this causes annoying problems. - * example: gss activates screensaver on timeout even though face is clearly - detected the whole time. - * workaround: make gss timeout be as long as possible -there are other problems. -the real fix is to combine the two. user activity should be any of {keyboard, -mouse, face detection}. diff --git a/TODO b/TODO index 6dae643..646efd4 100644 --- a/TODO +++ b/TODO @@ -1,18 +1,5 @@ FOR SCREENSAVER: -* use [Un]Inhibit together as a SimulateUserActivity workalike - * disablegss.py from http://ubuntuforums.org/showthread.php?t=284804 - * this method doesn't work either. tried in gss-poke.py -* xdg-screensaver suspend / resume to SimulateUserActivity - * http://tronche.com/gui/x/xlib-tutorial/2nd-program-anatomy.html - * http://portland.freedesktop.org/xdg-utils-1.0beta3/xdg-screensaver.html -* SimulateUserActivity - * does it work on other people's machines? - * find if other people have their gnome-screensaver run even if they set - screensaver timeout to 1 minute and run: - for ((i = 0; i < 999; i++)); do - sleep 50; - gnome-screensaver-command --poke; - done; +* gnome-screensaver-command --poke * find irc channel to ask if my understanding is correct * file bug * track down bug @@ -22,12 +9,14 @@ FOR SCREENSAVER: * no display window * no text printed to terminal * fire up the face detector only just before going to inactive mode. + * possibly this is how kreed's version works. read kreed's code to find out * that way the camera isn't running all the time - * maybe start 10 seconds before going inactive, then run until activity + * maybe start 10 seconds before going inactive, then run until activity, or 10 + seconds, whichever's first. * be more aggressive with turning off the screen. dim the screen as soon as it's not being looked at. turn it off soon thereafter. * could be enough to save battery. would need to power the camera sometimes, - but would save on backlight. need to test. + but would save on backlight. need to profile. * don't prevent sleep when face is detected, but user isn't actually looking at screen. * requires pose estimation. diff --git a/idle_x11.cpp b/idle_x11.cpp new file mode 100644 index 0000000..1b5e6e4 --- /dev/null +++ b/idle_x11.cpp @@ -0,0 +1,130 @@ +/* + * Copyright © 2009 Christopher Eby + * + * This file is part of Inertia. + * + * Inertia is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * Inertia is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * See for the full license text. + */ + +#include +#include +#include + +#include +#include +#include + +static Display *dpy = NULL; + +static void get_alarm(XSyncAlarm *alarm, XSyncCounter counter, XSyncTestType type, XSyncValue value) +{ + XSyncAlarmAttributes attrs; + + XSyncValue delta; + XSyncIntToValue(&delta, 0); + + static const unsigned long flags = XSyncCACounter | XSyncCATestType | XSyncCAValue | XSyncCADelta; + + attrs.trigger.counter = counter; + attrs.trigger.test_type = type; + attrs.trigger.wait_value = value; + attrs.delta = delta; + + if (*alarm) + XSyncChangeAlarm(dpy, *alarm, flags, &attrs); + else + *alarm = XSyncCreateAlarm(dpy, flags, &attrs); +} + +static void die(const char *errstr) +{ + fputs(errstr, stderr); + fflush(stderr); + exit(EXIT_FAILURE); +} + +bool wait_for_idle_time(int idle_time) +{ + static int xsync_event_base; + static XSyncAlarm idle_alarm = None; + static XSyncAlarm reset_alarm = None; + static XSyncCounter idle = None; + static XSyncValue idle_timeout; + + if (idle == None) { + if (!(dpy = XOpenDisplay(NULL))) + die("Could not open X11 display; exiting.\n"); + + int dummy; + if (!XQueryExtension(dpy, "XTEST", &dummy, &dummy, &dummy)) + die("XTEST extension not available; cannot reset idle time\n"); + + int xsync_error_base; + int xsync_major = SYNC_MAJOR_VERSION; + int xsync_minor = SYNC_MINOR_VERSION; + + if (!XSyncQueryExtension(dpy, &xsync_event_base, &xsync_error_base) || !XSyncInitialize(dpy, &xsync_major, &xsync_minor)) + die("No XSync extension; exiting.\n"); + + int i; + XSyncSystemCounter *counters = XSyncListSystemCounters(dpy, &i); + while (i--) + if (!strcmp(counters[i].name, "IDLETIME")) + idle = counters[i].counter; + XSyncFreeSystemCounterList(counters); + + if (idle == None) + die("No IDLETIME counter! xorg-server 1.3 and higher should support it. Exiting.\n"); + + XSyncIntToValue(&idle_timeout, idle_time * 1000); + get_alarm(&idle_alarm, idle, XSyncPositiveComparison, idle_timeout); + } + + XEvent ev; + + while (!XNextEvent(dpy, &ev)) { + if (ev.type == xsync_event_base + XSyncAlarmNotify) { + XSyncAlarmNotifyEvent *e = (XSyncAlarmNotifyEvent*)&ev; + + if (e->alarm == idle_alarm) { + int overflow; + XSyncValue reset_timeout; + XSyncValue minus_one; + + XSyncIntToValue(&minus_one, -1); + XSyncValueAdd(&reset_timeout, e->counter_value, minus_one, &overflow); + get_alarm(&reset_alarm, idle, XSyncNegativeComparison, reset_timeout); + + return true; + } else if (e->alarm == reset_alarm) { + get_alarm(&idle_alarm, idle, XSyncPositiveComparison, idle_timeout); + } + } + } + + return false; +} + +void reset_idle_time() +{ + if (!dpy) { + if (!(dpy = XOpenDisplay(NULL))) { + fputs("Could not open X11 display.\n", stderr); + return; + } + } + + XScreenSaverSuspend(dpy, True); + XSync(dpy, False); + XScreenSaverSuspend(dpy, False); + XSync(dpy, False); +} diff --git a/idle_x11.h b/idle_x11.h new file mode 100644 index 0000000..9bc48f1 --- /dev/null +++ b/idle_x11.h @@ -0,0 +1,3 @@ + +bool wait_for_idle_time(int idle_time); +void reset_idle_time(); diff --git a/oble.cpp b/oble.cpp index ab7d509..0e24b9e 100644 --- a/oble.cpp +++ b/oble.cpp @@ -40,12 +40,15 @@ #include #include #include "oble.h" +#include "idle_x11.h" using namespace std; // argument for cvFlip(src, dest, FLIP_TYPE) #define MIRROR 1 +#define DEBUG 0 + CvHaarClassifierCascade* load_object_detector(const char* cascade_path) { return (CvHaarClassifierCascade*)cvLoad(cascade_path); @@ -59,6 +62,7 @@ void detect_and_draw_objects(IplImage* image, CvMemStorage* storage = cvCreateMemStorage(0); CvSeq* faces; int i, scale = 1; + static int saw_last_time = 0; /* if the flag is specified, down-scale the input image to get a performance boost w/o loosing quality (perhaps) */ @@ -77,7 +81,25 @@ void detect_and_draw_objects(IplImage* image, if(0 < faces->total) { t_current = time(NULL); - //system("./gss-poke.py"); + if(DEBUG) + { + printf(":) face \n"); + } + if(saw_last_time) + { + if(DEBUG)printf("\t\tpoking\n"); + reset_idle_time(); + system("gnome-screensaver-command --poke"); + } + saw_last_time = 1; + } + else + { + saw_last_time = 0; + if(DEBUG) + { + printf(":( no face \n"); + } } /* draw all the rectangles */ @@ -105,7 +127,10 @@ void screensave(time_t t_current) if(elapse > timeout && elapse != last_elapse) { last_elapse = elapse; - printf("elapse = %d\n", elapse); + if(DEBUG) + { + printf("elapse = %d\n", elapse); + } if(!activated) { printf("activated\n"); @@ -161,7 +186,7 @@ int main(int argc, char** argv) detect_and_draw_objects(mirrored, cascade, 1); cvShowImage("mywindow", mirrored); // Do not release the frame! - screensave(t_current); + //screensave(t_current); //If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version), //remove higher bits using AND operator -- 2.30.2