Head nod detection from pitch angle

asked 2017-10-28 04:22:17 -0500

Ziniz gravatar image

I am making an android application that will detect driver's fatigue from head nod pose.

What I did:

  1. I have detected 68 facial landmarks from image using dlib library.
  2. Used solvePnP to find out rotation matrix and from that matrix I have got roll, pitch and yaw angles. Now, I have to detect head nod from pitch angle.

My Problem:

  1. How to set a threshold value so that an angle below or above the threshold can be said as a head nod?
  2. It results some negative angles. What does a negative angle mean in 3 dimensional axis?

My code:

 void getEulerAngles(Mat &rotCamerMatrix,Vec3d &eulerAngles)
     Mat cameraMatrix,rotMatrix,transVect,rotMatrixX,rotMatrixY,rotMatrixZ;
     double* _r = rotCamerMatrix.ptr<double>();
     double projMatrix[12] = {_r[0],_r[1],_r[2],0,

      decomposeProjectionMatrix( Mat(3,4,CV_64FC1,projMatrix),

int renderToMat(std::vector<full_object_detection>& dets, Mat& dst)
     Scalar color;
     std::vector<cv::Point2d> image_points;
     std::vector<cv::Point3d> model_points;
     string disp;

     int sz = 3,l;
     color = Scalar(0,255,0);
     double p1,p2,p3,leftear,rightear,ear=0,yawn=0.00,yaw=0.00,pitch=0.00,roll=0.00;
     //I am calculating only for one face.. so assuming l=1
     for(unsigned long idx = 0; idx < l; idx++)
          Point2d(dets[idx].part(30).x(),dets[idx].part(30).x() ) );
          image_points.push_back(Point2d(dets[idx].part(8).x(),dets[idx].part(8).x() ) );
          image_points.push_back(Point2d(dets[idx].part(36).x(),dets[idx].part(36).x() ) );
          image_points.push_back(Point2d(dets[idx].part(45).x(),dets[idx].part(45).x() ) );
          image_points.push_back(Point2d(dets[idx].part(48).x(),dets[idx].part(48).x() ) );
          image_points.push_back(Point2d(dets[idx].part(54).x(),dets[idx].part(54).x() ) );
     double focal_length = dst.cols;
     Point2d center = cv::Point2d(dst.cols/2.00,dst.rows/2.00);
     cv::Mat camera_matrix = (cv::Mat_<double>(3.00,3.00) << focal_length, 0, center.x, 0, focal_length, center.y, 0, 
0, 1);
     cv::Mat dist_coeffs = cv::Mat::zeros(4,1,cv::DataType<double>::type);
     cv::Mat rotation_vector; //s Rotation in axis-angle form
     cv::Mat translation_vector;
     cv::Mat rotCamerMatrix1;

          model_points.push_back(cv::Point3d(0.0f, 0.0f, 0.0f));
          model_points.push_back(cv::Point3d(0.0f, -330.0f, -65.0f));
          model_points.push_back(cv::Point3d(-225.0f, 170.0f, -135.0f));
          model_points.push_back(cv::Point3d(225.0f, 170.0f, -135.0f));
          model_points.push_back(cv::Point3d(-150.0f, -150.0f, -125.0f));
          model_points.push_back(cv::Point3d(150.0f, -150.0f, -125.0f));
          cv::solvePnP(model_points, image_points, camera_matrix, dist_coeffs,rotation_vector, translation_vector);
          Vec3d eulerAngles;

          yaw   = eulerAngles[1];
          pitch = eulerAngles[0];
          roll  = eulerAngles[2];
         /*My problem begins here. I don't know how to set a threshold value for pitch so that I can say a value below or 
above the pitch is a head nod!*/

     return 0;
edit retag flag offensive close merge delete