Blame view

main.cpp 6.25 KB
7fb0aefd   Rentrag   Ajout des rendues...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
  #include "opencv2/objdetect.hpp"
  #include "opencv2/videoio.hpp"
  #include "opencv2/highgui.hpp"
  #include "opencv2/imgproc.hpp"
  #include <iostream>
  #include <stdio.h>
  #include <unistd.h>
  #include <string.h>
  #include <X11/Xlib.h>
  
  /* Cadriage de la fenêtre
   * ----------> x
   * |
   * |
   * |
   * |
   * v
   * y
   * 
   * xleft: x < 280
   * xmid: 280 < x < 400
   * xright: x > 400
   * yup; y < 90
   * ymid: 90 < y < 135
   * ydown: y > 135
   */
  
  /* Pistes d'améliorations
   *
   * Vitesse de curseur variable : La vitesse est pour l'instant fixe, une évolution exponentielle semblable au track pad est envisageable
   * Détection du visage trop sensible à la lumière: La détection n'est qu'efficace que lorsque le visage est éclairée directement par une source lumineuse
   * Détection des yeux avec des lunette: Mes lunettes sont parfois reconnue comme d'autres yeux au dessus de mes vrais yeux ce qui empèche l'utilisation du clique
   * 
   *
   */
  
  
  int facePosX, facePosY;
  
  using namespace std;
  using namespace cv;
  
  void detectAndDisplay( Mat frame );
  void click (Display *display, int button);
  void eyeClick(std::vector<Rect> eyes);
  
  
  //choisit lcran de la machine où les coordonées de la souris seront donnés (le code ne marche qu'avec des machine possédant un seul écran)
  Display* dpy = XOpenDisplay(0);
  int scr = XDefaultScreen(dpy);
  Window root_window = XRootWindow(dpy, scr);
  
  //calcul la taille et de l'ecran
  int screenheight = DisplayHeight(dpy, scr);
  int screenwidth  = DisplayWidth(dpy, scr);
  
  //init la position de la souris au centre de lcran
  int mousePosX = screenwidth/2;
  int mousePosY = screenheight/2;
  int mouseSpeed = 5;
  
  int clickTimer = 0;
  int maxClickTimer = 10;
  
  String face_cascade_name = "haarcascade_frontalface_alt.xml";
  String eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
  CascadeClassifier face_cascade;
  CascadeClassifier eyes_cascade;
  
  String window_name = "Capture - Face detection";
  
  int main( void )
  {
      VideoCapture capture;
      Mat frame;
      //-- 1. Load the cascades
      if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading face cascade\n"); return -1; };
      if( !eyes_cascade.load( eyes_cascade_name ) ){ printf("--(!)Error loading eyes cascade\n"); return -1; };
      //-- 2. Read the video stream
      capture.open( -1 );
      if ( ! capture.isOpened() ) { printf("--(!)Error opening video capture\n"); return -1; }
      while ( capture.read(frame) )
      {
          if( frame.empty() )
          {
              printf(" --(!) No captured frame -- Break!");
              break;
          }
          //-- 3. Apply the classifier to the frame
          detectAndDisplay( frame );
          char c = (char)waitKey(10);
          if( c == 27 ) { break; } // escape
          XFlush(dpy);
      }
      
      return 0;
  }
  
  void refreshMousePosition(std::vector<Rect> faces)
  {
      int xPos, yPos;
      for ( size_t i = 0; i < faces.size(); i++)
      {
          //posistion analyse
          if (faces[i].x < 280) xPos = -1;
          if (faces[i].x > 280 && faces[i].x < 400) xPos = 0;
          if (faces[i].x > 400) xPos = 1;
          if (faces[i].y < 90) yPos = -1;
          if (faces[i].y > 90 && faces[i].y < 135) yPos = 0;
          if (faces[i].y > 135) yPos = 1;
  
          //position print
          switch (xPos)
          {
              case -1:
              mousePosX += mouseSpeed;
              break;
              case 0:
              break;
              case 1:
              mousePosX -= mouseSpeed;
              break;    
          }
          switch (yPos)
          {
              case -1:
              mousePosY -= mouseSpeed;
              break;
              case 0:
              break;
              case 1:
              mousePosY += mouseSpeed;
              break;    
          }
          XWarpPointer(dpy, None, root_window, 0, 0, 0, 0, mousePosX, mousePosY);
      }
  }
  
  void detectAndDisplay( Mat frame )
  {
      std::vector<Rect> faces;
      Mat frame_gray;
      cvtColor( frame, frame_gray, COLOR_BGR2GRAY );
      equalizeHist( frame_gray, frame_gray );
      //-- Detect faces
      face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CASCADE_SCALE_IMAGE, Size(30, 30) );
      refreshMousePosition(faces);
      for ( size_t i = 0; i < faces.size(); i++ )
      {
          Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );
          ellipse( frame, center, Size( faces[i].width/2, faces[i].height/2 ), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
          Mat faceROI = frame_gray( faces[i] );
          std::vector<Rect> eyes;
          //-- In each face, detect eyes
          eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CASCADE_SCALE_IMAGE, Size(30, 30) );
          eyeClick(eyes);
          for ( size_t j = 0; j < eyes.size(); j++ )
          {
              Point eye_center( faces[i].x + eyes[j].x + eyes[j].width/2, faces[i].y + eyes[j].y + eyes[j].height/2 );
              int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
              circle( frame, eye_center, radius, Scalar( 255, 0, 0 ), 4, 8, 0 );
          }
      }
      //-- Show what you got
      imshow( window_name, frame );
  }
  
  void eyeClick(std::vector<Rect> eyes)
  {
      if (eyes.size() < 1)
      {
          if (clickTimer >= maxClickTimer)
          {
              click(dpy, Button1);
              clickTimer = 0;
          }
          else
          {
              clickTimer++;
          }
      }
      else
      {
          clickTimer = 0;
      }
  }
  
  void click (Display *display, int button)
  {
    // Create and setting up the event
    XEvent event;
    memset (&event, 0, sizeof (event));
    event.xbutton.button = button;
    event.xbutton.same_screen = True;
    event.xbutton.subwindow = DefaultRootWindow (display);
    while (event.xbutton.subwindow)
      {
        std::cout << "Click" << std::endl;
        event.xbutton.window = event.xbutton.subwindow;
        XQueryPointer (display, event.xbutton.window,
  		     &event.xbutton.root, &event.xbutton.subwindow,
  		     &event.xbutton.x_root, &event.xbutton.y_root,
  		     &event.xbutton.x, &event.xbutton.y,
  		     &event.xbutton.state);
      }
    // Press
    event.type = ButtonPress;
    if (XSendEvent (display, PointerWindow, True, ButtonPressMask, &event) == 0)
      fprintf (stderr, "Error to send the event!\n");
    XFlush (display);
    usleep (1);
    // Release
    event.type = ButtonRelease;
    if (XSendEvent (display, PointerWindow, True, ButtonReleaseMask, &event) == 0)
      fprintf (stderr, "Error to send the event!\n");
    XFlush (display);
    usleep (1);
  }