我正在制作一个Android应用程序,它将通过头点头姿势检测驾驶员的疲劳程度。
What I did:

  • 我已经使用dlib库从图像中检测到68个面部标志。
  • 使用solvePnP找出旋转矩阵,然后从该矩阵中获得滚动,俯仰和偏航角。
    现在,我必须从俯仰 Angular 检测头部点头。
  • My Problem:
  • 如何设置阈值,以便将低于或高于该阈值的 Angular 称为头部点头?
  • 它导致一些负角。 3维轴上的负角是什么意思?

  • 我的代码:
     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,
                      _r[3],_r[4],_r[5],0,
                      _r[6],_r[7],_r[8],0};
    
          decomposeProjectionMatrix( Mat(3,4,CV_64FC1,projMatrix),
                           cameraMatrix,
                           rotMatrix,
                           transVect,
                           rotMatrixX,
                           rotMatrixY,
                           rotMatrixZ,
                           eulerAngles);
    
     }
    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;
         l=dets.size();
         //I am calculating only for one face.. so assuming l=1
         for(unsigned long idx = 0; idx < l; idx++)
         {
              image_points.push_back(
              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;
    
         if(l!=0)
         {
              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);
              Rodrigues(rotation_vector,rotCamerMatrix1);
              Vec3d eulerAngles;
              getEulerAngles(rotCamerMatrix1,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;
    }
    

    最佳答案

    首先,您必须了解在3D上下文中如何使用3个 Angular 。基本上,它们相对于原点旋转3D空间中的对象(原点可以根据上下文而变化),但是如何应用3个 Angular ?

    这个问题可以表示为:它们以什么顺序旋转对象。如果应用偏航,则俯仰然后滚动可能会给您与相反方向的物体不同的方向。话虽如此,您必须了解这些值代表什么,以了解如何处理它们。

    现在,您问什么是一个好的阈值,这取决于。什么?好吧,按照应用顺序。例如,如果您先以45度应用俯仰,使其俯仰,然后再应用180度滚动,则俯仰,因此很难定义阈值。

    由于有了模型点,因此您可以创建一个3D旋转矩阵并将其以不同的俯仰 Angular 应用于它们(其余 Angular 将为0,因此此处的顺序并不重要),并对其进行可视化并选择一个考虑点头。这有点主观,所以您应该这样做。

    现在,到第二个问题。答案再次是,这取决于。这次是什么时候?你可能会问。很简单,您的系统是左手还是右手?在一种情况下,这意味着顺时针旋转,而在另一种情况下则逆时针旋转,负号会更改方向。因此,在左手系统中,它将是顺时针方向,负号将是逆时针方向。右手系统将逆时针旋转,负号将使其顺时针旋转。

    作为建议,假设z轴朝后,可以制作一个 vector (0,0,-1)。然后对其施加旋转并将其投影到与z轴平行的2D平面上,这里取 vector 的尖端并查看此处的 Angular 是多少。这样,您可以确定自己正在得到什么。

    09-06 17:10