title: Eye Blink detection OpenCV C++
body: <p>I am trying to write an eye blink detector but it does not work properly.</p>
  
  <p>It finds the face and eyes properly, then I try to find a circle in the eye area (the pupil) but it is not always found. When it <em>is</em> found, it detects a blink although the eye is not blinking (the counter is incremented).</p>
  
  <p>I have tried different methods and filters (HoughCircles, Canny, threshold, medianBlur, smooth) but it does not change.</p>
  
  <p>Here is my code:</p>
  
  <pre><code>#include "stdafx.h"
  #include &lt;stdio.h&gt;
  #include &lt;iostream&gt;
  #include &lt;vector&gt;
  #include &lt;math.h&gt;
  #include &lt;iomanip&gt;
  #include &lt;sstream&gt;
  #include &lt;string&gt;
  
  #include &lt;opencv2\objdetect\objdetect.hpp&gt;
  #include &lt;opencv2\highgui\highgui.hpp&gt;
  #include &lt;opencv2\imgproc\imgproc.hpp&gt;
  #include &lt;opencv2\video\tracking.hpp&gt;
  #include "opencv2/opencv.hpp"
  
  // Include OpenCV's C++ Interface
  #include "opencv2/opencv.hpp"
  
  
  const float eyeTop = 0.26f;     //y
  const float eyeSide = 0.16f;  //x
  const float eyeHeight = 0.28f;  //h
  const float eyeWidth = 0.65f;       //w
  const int calibrationDefault = 100;
  
  int blinknumber =0;
  int calibrationFace = calibrationDefault;
  
  bool leftEyeOpen = true;
  bool rightEyeOpen = true;
  int blinkNumberLeft = 0;
  int blinkNumberRight = 0;
  
  using namespace cv;
  using namespace std;
  
  const std::string casceye_name = "C:\\Users\\Hossein Hezarpisheh\\Documents\\Visual Studio 2010\\Projects\\projek1\\haarcascade_mcs_eyepair_big.xml";
  const std::string face_cascade_name = "C:\\Users\\Hossein Hezarpisheh\\Documents\\Visual Studio 2010\\Projects\\projek1\\haarcascade_frontalface_alt.xml";
  
  Mat lastFace;
  Mat actualFace;
  
  void headTracing(Mat grayImage, Mat image, CascadeClassifier casceye, CascadeClassifier cascFace, Rect &amp;faceArea);
  Rect detectLargestObject(Mat grayImage, CascadeClassifier cascFace);
  void eyeTracking(Mat &amp;actualFace, Mat &amp;lastFace,int &amp;blinknumber);
  void getEyes(Mat &amp;face, Mat &amp;eye);
  
  namespace patch
  {
  template &lt; typename T &gt; string to_string(T n )
  {
      ostringstream stm ;
      stm &lt;&lt; n ;
      return stm.str() ;
  }
  }
  
  int main()
  {
   Rect faceArea; 
   CascadeClassifier cascFace, casceye;
  
  if (!cascFace.load(face_cascade_name)){ printf("--(!)Error loading face cascade\n"); return -1; };
  if (!casceye.load(casceye_name)){ printf("--(!)Error loading eyes cascade\n"); return -1; };
  
  
  cout &lt;&lt; "\n\tESC - Programm beenden\n\tc - zaehler auf 0 setzen\n\n";
  
  namedWindow("Blinzel Erkennung", CV_WINDOW_AUTOSIZE);
  
  VideoCapture capture(0);
  if (!capture.isOpened())
  {
      cout&lt;&lt;"Kamera wurde nicht gefunden!"&lt;&lt;endl;
      return 1;
  }
  
  Mat Image;
  
  while (1)
  {
      Mat GrayImage;
      capture &gt;&gt; Image;
  
      if (Image.empty()){                                         
          continue;
      }
  
      flip(Image, Image, 1);                                  
      cvtColor(Image, GrayImage, CV_BGR2GRAY);
  
      headTracing(GrayImage, Image, casceye , cascFace, faceArea);        
  
  
      switch (waitKey(2)) {
      case 27:
   return 0;                                                              
          break;
  case120:                                                                        
          calibrationFace = 0;
          break;
  
      case 99:                                                                        // c key - zähler auf 0 setzen
          leftEyeOpen = true;
          rightEyeOpen = true;
          blinkNumberLeft = 0;
          blinkNumberRight = 0;
          break;
      }
  }
  return 0;
  }
  
  
  
  
  void calcFlow(const Mat&amp; flow, Mat&amp; cflowmap, int step, int &amp;globalMoveX, int &amp;globalMoveY)
  {
  int localMoveX = 0;
  int localMoveY = 0;
  
  for (int y = 0; y &lt; cflowmap.rows; y += step)
  {
      for (int x = 0; x &lt; cflowmap.cols; x += step)
      {
          const Point2f&amp; fxy = flow.at&lt;Point2f&gt;(y, x);
  
          localMoveX = localMoveX + fxy.x;
          localMoveY = localMoveY + fxy.y;
          }
      }
  
  globalMoveX = (localMoveX / (cflowmap.cols * cflowmap.rows))*2;                         
  globalMoveY = (localMoveY / (cflowmap.rows * cflowmap.cols))*2;
  }
  
  
  void headTracing(Mat grayImage, Mat image, CascadeClassifier casceye, CascadeClassifier cascFace, Rect &amp;faceArea) {
  
  Rect face = detectLargestObject(grayImage, cascFace);
  if (face.width == 0 &amp;&amp; face.height == 0) {
      imshow("Ergebnis", image);                                  
      return;                                                             
  }
  
  calibrationFace = calibrationFace - 1;
  
  if (faceArea.height == 0|| calibrationFace &lt; 1) {           
      faceArea = face;
      lastFace = grayImage(face);
      calibrationFace = calibrationDefault;                           
  }
  else {                                                      
  
      actualFace = grayImage(faceArea);
  
      Mat flow, cflow;
      calcOpticalFlowFarneback(lastFace, actualFace, flow, 0.5, 3, 15, 3, 5, 1.2, 0);
  
      cvtColor(lastFace, cflow, CV_GRAY2BGR);
  
      int globalMoveX, globalMoveY;
  
      calcFlow(flow, cflow, 1, globalMoveX, globalMoveY);
  
  
      faceArea.x = faceArea.x + globalMoveX;      
      faceArea.y = faceArea.y + globalMoveY;
  
      if (faceArea.x &lt; 0) {                                       
          faceArea.x = 0;
      }
      if (faceArea.y &lt; 0) {
          faceArea.y = 0;
      }
  
      if (faceArea.x + faceArea.width &gt; image.size().width - 1) {     
          faceArea.x = image.size().width - faceArea.width - 1;
      }
      if (faceArea.y + faceArea.height &gt; image.size().height - 1) {
          faceArea.y = image.size().height - faceArea.height - 1;
      }
      //rectangle(image,faceArea, 12);                
      actualFace = grayImage(faceArea);               
  
  
      eyeTracking(actualFace, lastFace,blinknumber);   //jetzt haben wir zwei stabilisierte Frames(aktuell&amp;vorherige) nun können wir die Bewegung berechnen
      swap(lastFace, actualFace);  //aktuelles Frame wird zu vorherigen Frame und umgekehrt
  }
  putText(image,patch::to_string(blinknumber), cvPoint(520, 45), FONT_HERSHEY_COMPLEX_SMALL, 1.5, cvScalar(100, 100, 255), 1, CV_AA);
  
  imshow("Ergebnis", image);       //Ergebniss anzeigen
  }
  
  Rect detectLargestObject(Mat grayImage, CascadeClassifier cascFace)  {
  
  Rect value;
  
  vector&lt;Rect&gt; faces;
  cascFace.detectMultiScale(grayImage, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE | CV_HAAR_FIND_BIGGEST_OBJECT, Size(150, 150), Size(300, 300));
  if (faces.size() &gt; 0) {
      return faces[0];
  }
  else {
      return value;
  }
  }
  
  void eyeTracking(Mat &amp;actualFace, Mat &amp;lastFace,int &amp;blinknumber) {
  
  Mat eyeActual;
  getEyes(actualFace, eyeActual);
  Mat eyeActualGray;
  cvtColor(eyeActual, eyeActualGray, COLOR_GRAY2BGR);
  
  //medianBlur(eyeActual, eyeActual,5);
  //cvtColor(eyeActual, eyeActualGray, COLOR_BGR2GRAY);
  
  namedWindow("Kreis", CV_WINDOW_AUTOSIZE);
  
  //Canny(eyeActual,eyeActual,5,70,3);
  medianBlur(eyeActual, eyeActual,5);
  //threshold(eyeActual,eyeActual,50,200,THRESH_BINARY);
  //vector&lt;vector&lt;Point&gt; &gt; contours;
  
  vector &lt;Vec3f&gt; circles;
  
  //findContours(eyeActual.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
  //drawContours(eyeActual, contours, -1, CV_RGB(255,255,255), -1);
  
  HoughCircles( eyeActual, circles, CV_HOUGH_GRADIENT, 1, eyeActual.rows/8, 50,25,5,15 );
  
  for( size_t i = 0; i &lt; circles.size(); i++ )
    {
  
      Vec3i c = circles[i];
      //circle(eyeActualGray,Point(c[0], c[1]), c[2], Scalar(0,0,255), 2);
      circle( eyeActualGray, Point(c[0], c[1]), 2, Scalar(0,255,0), 2);
  
      blinknumber=blinknumber+1;
  
  }
      imshow("Kreis", eyeActualGray);
  
  }
  
  void getEyes(Mat &amp;face, Mat &amp;eye) {
  
  Size faceSize = face.size();
  
  int eye_area_width = faceSize.width * eyeWidth;
  int eye_area_height = faceSize.width *eyeHeight;
  int eye_area_top = faceSize.height *eyeTop;
  
  Rect rightEyeArea(faceSize.width*eyeSide, eye_area_top, eye_area_width, eye_area_height);
  eye = face(rightEyeArea);
  }
  </code></pre>