首页 > 其他分享 >人脸对齐和关键点计算估计姿态代码

人脸对齐和关键点计算估计姿态代码

时间:2024-10-18 16:17:22浏览次数:8  
标签:landmarks back points 人脸 push 对齐 pts cv 关键点

1.人脸对齐代码

1.1定义结构体

#include <iostream>
#include <opencv2/opencv.hpp>
#include <onnxruntime_cxx_api.h>
#include <vector>
#include <cmath>
#include <filesystem>

using namespace cv;
typedef struct FacePts
{
    float x[5], y[5];
} FacePts;

1.2相似变换函数

cv::Mat similarity_transform(std::vector<cv::Point2f>& from_points, std::vector<cv::Point2f>& to_points)
{
    cv::Mat warp_mat(2, 3, CV_64FC1);
    cv::Point2f mean_from, mean_to;
    double sigma_from = 0, sigma_to = 0;
    cv::Mat cov(2, 2, CV_64FC1);
    cov.setTo(0.0);
    for (int i = 0; i < from_points.size(); ++i)
    {
        mean_from.x += from_points[i].x; mean_from.y += from_points[i].y;
        mean_to.x += to_points[i].x; mean_to.y += to_points[i].y;
    }
    mean_from.x /= from_points.size(); mean_from.y /= from_points.size();
    mean_to.x /= from_points.size(); mean_to.y /= to_points.size();
    //std::cout << "cov:" << cov.ptr<double>(0)[0] << std::endl;
    for (int i = 0; i < from_points.size(); ++i)
    {
        sigma_from += (from_points[i].x - mean_from.x) * (from_points[i].x - mean_from.x) + (from_points[i].y - mean_from.y) * (from_points[i].y - mean_from.y);
        sigma_to += (to_points[i].x - mean_to.x) * (to_points[i].x - mean_to.x) + (to_points[i].y - mean_to.y) * (to_points[i].y - mean_to.y);
        cov.ptr<double>(0)[0] += (to_points[i].x - mean_to.x) * (from_points[i].x - mean_from.x);
        cov.ptr<double>(1)[0] += (to_points[i].y - mean_to.y) * (from_points[i].x - mean_from.x);
        cov.ptr<double>(0)[1] += (to_points[i].x - mean_to.x) * (from_points[i].y - mean_from.y);
        cov.ptr<double>(1)[1] += (to_points[i].y - mean_to.y) * (from_points[i].y - mean_from.y);
    }

    sigma_from /= from_points.size();
    sigma_to /= from_points.size();
    cov.ptr<double>(0)[0] /= from_points.size();
    cov.ptr<double>(0)[1] /= from_points.size();
    cov.ptr<double>(1)[0] /= from_points.size();
    cov.ptr<double>(1)[1] /= from_points.size();
    //std::cout << "cov:" << cov.ptr<double>(0)[0] << std::endl;
    cv::Mat u(2, 2, CV_64FC1);
    cv::Mat v(2, 2, CV_64FC1);
    cv::Mat s(2, 2, CV_64FC1);
    cv::Mat d(2, 2, CV_64FC1);
    cv::Mat dd(2, 2, CV_64FC1);
    cv::SVD::compute(cov, d, u, v);
    //s = identity_matrix(cov);
    s.ptr<double>(1)[1] = 1; s.ptr<double>(0)[0] = 1; s.ptr<double>(0)[1] = 0; s.ptr<double>(1)[0] = 0;
    if (cv::determinant(cov) < 0 || cv::determinant(cov) == 0 && cv::determinant(u) * cv::determinant(v) < 0)
    {
        if (d.ptr<double>(1)[1] < d.ptr<double>(0)[0])
            s.ptr<double>(1)[1] = -1;
        else
            s.ptr<double>(0)[0] = -1;;
    }
    cv::Mat r(2, 2, CV_64FC1);
    v = -v;
    r = -u * s * v;
    double c = 1;
    dd.ptr<double>(0)[0] = d.ptr<double>(0)[0];
    dd.ptr<double>(0)[1] = 0;
    dd.ptr<double>(1)[0] = 0;
    dd.ptr<double>(1)[1] = d.ptr<double>(0)[1];
    if (sigma_from != 0)
        c = 1.0 / sigma_from * trace(dd * s).val[0];
    cv::Mat t(2, 1, CV_64FC1), mean_f(2, 1, CV_64FC1), mean_t(2, 1, CV_64FC1);
    mean_f.ptr<double>(0)[0] = mean_from.x;
    mean_f.ptr<double>(1)[0] = mean_from.y;
    mean_t.ptr<double>(0)[0] = mean_to.x;
    mean_t.ptr<double>(1)[0] = mean_to.y;
    mean_t = mean_t - c * r * mean_f;
    warp_mat.ptr<double>(0)[0] = c * r.ptr<double>(0)[0];
    warp_mat.ptr<double>(0)[1] = c * r.ptr<double>(0)[1];
    warp_mat.ptr<double>(0)[2] = mean_t.ptr<double>(0)[0];
    warp_mat.ptr<double>(1)[0] = c * r.ptr<double>(1)[0];
    warp_mat.ptr<double>(1)[1] = c * r.ptr<double>(1)[1];
    warp_mat.ptr<double>(1)[2] = mean_t.ptr<double>(1)[0];
    return warp_mat;
}

 1.3抠图

cv::Mat Align_and_CropFace(cv::Mat& image, FacePts pts, FacePts& outmarks, const int Size=112, const double padding=0.0f)
{
    cv::Point2f srcTri[5];
    cv::Point2f dstTri[5];
    std::vector<cv::Point2f> src;
    std::vector<cv::Point2f> dst;
    // Average positions of face points 0-4
   /* double mean_face_shape_x[] = {
        0.2281715, 0.7520815, 0.490127, 0.25419, 0.726104
    };
    double mean_face_shape_y[] = {
        0.224078, 0.224078, 0.515625, 0.780233, 0.780233
    };*/
    /* arcface_src = np.array([
        [38.2946, 51.6963],
            [73.5318, 51.5014],
            [56.0252, 71.7366],
            [41.5493, 92.3655],
            [70.7299, 92.2041]], dtype = np.float32)
            */
    double mean_face_shape_x[] = {
       0.341916, 0.656534, 0.500225, 0.370976,0.631517
    };
    double mean_face_shape_y[] = {
        0.461574,0.459834, 0.640505, 0.8246919, 0.823251
    }; 

    for (int i = 0; i < 5; i++)
    {
        mean_face_shape_x[i] = (mean_face_shape_x[i] + padding) / (2 * padding + 1);
        mean_face_shape_y[i] = (mean_face_shape_y[i] + padding) / (2 * padding + 1);

        src.push_back(Point2f(pts.x[i], pts.y[i]));
        dst.push_back(Point2f(mean_face_shape_x[i] * Size, mean_face_shape_y[i] * Size));

    }
    Mat det = similarity_transform(src, dst);
    //	Mat warp_mat0(2, 3, CV_64FC1);

    Mat warp_frame(Size, Size, CV_8UC3);
    warpAffine(image, warp_frame, det, warp_frame.size());

    for (int i = 0; i < 5; i++)
    {
        outmarks.x[i] = det.ptr<double>(0)[0] * pts.x[i] + det.ptr<double>(0)[1] * pts.y[i] + det.ptr<double>(0)[2];
        outmarks.y[i] = det.ptr<double>(1)[0] * pts.x[i] + det.ptr<double>(1)[1] * pts.y[i] + det.ptr<double>(1)[2];
    }

    return warp_frame;
}

1.3判断人脸角度是否过大

bool getFacePose(FacePts facePts, const float seg=2.5)
{
    //eye
    //num0++;
    float dis_eye = (facePts.x[1] - facePts.x[0]) / seg;
    float eye_mid = (facePts.x[1] + facePts.x[0]) / 2;

    //mouth
    int th1 = 1000 * fabs(facePts.x[2] - eye_mid) / dis_eye;
    float dis_mouth = (facePts.x[4] - facePts.x[3]) / seg;
    float mouth_mid = (facePts.x[4] + facePts.x[3]) / 2;

    int th2 = 1000 * abs(facePts.x[2] - mouth_mid) / dis_mouth;
    //noise
    float dis_noise = (facePts.y[3] + facePts.y[4]) * 0.5 - (facePts.y[0] + facePts.y[1]) * 0.5;
    float dis_noise_ratio = fabs(((facePts.y[3] + facePts.y[4]) * 0.5 - facePts.y[2]) / (facePts.y[2] - ((facePts.y[0] + facePts.y[1]) * 0.5)));
    int th3 = 1000 * dis_noise_ratio;
    //point_ << name << " " << fabs(facePts.y[3] - facePts.y[4]) << " " << fabs(facePts.x[2] - eye_mid) << " " << dis_eye << " " << fabs(facePts.x[2] - mouth_mid) << " " << dis_mouth << " " << dis_noise_ratio << std::endl;
    //ratio:1.5 0.1 change to 1.35 0.15
    if (/*dis_noise_ratio > 2.55 || dis_noise_ratio < 0.27 ||*/ fabs(facePts.x[2] - eye_mid) > dis_eye || fabs(facePts.x[2] - mouth_mid) > dis_mouth)
    {
        //imwrite("./save/0/" +num2str(num0)+"_" +num2str(th1)+"_"+num2str(th2)+"_"+num2str(th3)+".jpg",temp);
        return false;
    }

    else
    {
        if (dis_mouth < 21)
            return false;
        //imwrite("./save/1/" + num2str(num0) +"_"+ num2str(th1) + "_" + num2str(th2) + "_" + num2str(th3) + ".jpg", temp);
        else
            return true;
    }

}

2.人脸姿态估计代码

// 姿态估计算法,主要用以估计输入目标的三维欧拉角,其大致可分为两类:一类是通过2D标定信息来估计3D姿态信息的算法,如先计算人脸的关键点,然后选取一个参考系(平均正脸的关键点),计算关键点和参考系的变换矩阵,然后通过迭代优化的算法来估计人脸的姿态(可参考opencv中的SolvePnP算法), 另一类就是通过数据驱动的方式训练一个回归器,由该回归器对输入人脸的块进行一个直接的预测。两类方法各有利弊,第一类算法为landmark-based,第二类为landmark-free

//原文链接:https ://blog.csdn.net/minstyrain/article/details/82391052
//计算用人脸关键点坐标所在参考图像
//yaw是double三维旋转之左右旋转角[-90(左), 90(右)]
//pitch是double三维旋转之俯仰角度[-90(上), 90(下)]
//roll是	double平面内旋转角[-180(逆时针), 180(顺时针)]
std::vector<float> getFacePose(std::vector<cv::Point>& landmarks, cv::Mat img_face)
{
    std::vector<float> facePose;//pitch yaw row
    // 3D model points.
    std::vector<cv::Point3d> model_points;
    model_points.push_back(cv::Point3d(0.0f, 0.0f, 0.0f));               // Nose tip
    model_points.push_back(cv::Point3d(-165.0f, 170.0f, -135.0f));
    model_points.push_back(cv::Point3d(165.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));
    //model_points.push_back(cv::Point3d(0.0f, -330.0f, -65.0f));          // Chin
    //model_points.push_back(cv::Point3d(-225.0f, 170.0f, -135.0f));       // Left eye left corner
    //model_points.push_back(cv::Point3d(225.0f, 170.0f, -135.0f));        // Right eye right corner
    //model_points.push_back(cv::Point3d(-150.0f, -150.0f, -125.0f));      // Left Mouth corner
    //model_points.push_back(cv::Point3d(150.0f, -150.0f, -125.0f));       // Right mouth corner

    std::vector<cv::Point2d> image_points;
    //image_points.push_back(cv::Point2d(landmarks[2].x, landmarks[2].y)); 
    float cent_eye = landmarks[0].y / 2 + landmarks[1].y / 2;
    float cent_mouth = landmarks[4].y / 2 + landmarks[3].y / 2;
   // image_points.push_back(cv::Point2d(landmarks[3].x / 2 + landmarks[4].x / 2, cent_mouth + 1.04 * (cent_mouth - landmarks[2].y)));    // Chin 1.03倍嘴巴到鼻子距离
 //   image_points.push_back(cv::Point2d(landmarks[0].x, landmarks[0].y));     // Left eye left corner
  //  image_points.push_back(cv::Point2d(landmarks[1].x, landmarks[1].y));    // Right eye right corner
  //  image_points.push_back(cv::Point2d(landmarks[3].x, landmarks[3].y));    // Left Mouth corner
  //  image_points.push_back(cv::Point2d(landmarks[4].x, landmarks[4].y));    // Right mouth corne
    image_points.push_back(cv::Point2d(landmarks[2].x, landmarks[2].y));
    image_points.push_back(cv::Point2d(landmarks[0].x, landmarks[0].y));
    image_points.push_back(cv::Point2d(landmarks[1].x, landmarks[1].y));
    image_points.push_back(cv::Point2d(landmarks[3].x, landmarks[3].y));
    image_points.push_back(cv::Point2d(landmarks[4].x, landmarks[4].y));
  // Camera internals
    double focal_length = img_face.cols; // Approximate focal length.
    double focal_length_x = img_face.cols; // Approximate focal length.
    double focal_length_y = img_face.rows; // Approximate focal length.
    //focal_length = img_face.cols / tan(60 / 2 * CV_PI / 180);
    focal_length = img_face.cols;
    cv::Point2d center = cv::Point2d(img_face.cols / 2, img_face.rows / 2);
    cv::Mat camera_matrix = (cv::Mat_<double>(3, 3) << 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); // Assuming no lens distortion

    cv::Mat rotation_vector; // Rotation in axis-angle form
    cv::Mat translation_vector;

    // Solve for pose
    cv::solvePnP(model_points, image_points, camera_matrix, dist_coeffs, rotation_vector, translation_vector,false, SOLVEPNP_SQPNP);


    //cv2::Rodrigues
    /*
    # 从旋转向量转换为欧拉角
def get_euler_angle(rotation_vector):
    # calculate rotation angles
    theta = cv2.norm(rotation_vector, cv2.NORM_L2)

    # transformed to quaterniond
    w = math.cos(theta / 2)
    x = math.sin(theta / 2)*rotation_vector[0][0] / theta
    y = math.sin(theta / 2)*rotation_vector[1][0] / theta
    z = math.sin(theta / 2)*rotation_vector[2][0] / theta

    ysqr = y * y
    # pitch (x-axis rotation)
    t0 = 2.0 * (w * x + y * z)
    t1 = 1.0 - 2.0 * (x * x + ysqr)
    print('t0:{}, t1:{}'.format(t0, t1))
    pitch = math.atan2(t0, t1)

    # yaw (y-axis rotation)
    t2 = 2.0 * (w * y - z * x)
    if t2 > 1.0:
        t2 = 1.0
    if t2 < -1.0:
        t2 = -1.0
    yaw = math.asin(t2)

    # roll (z-axis rotation)
    t3 = 2.0 * (w * z + x * y)
    t4 = 1.0 - 2.0 * (ysqr + z * z)
    roll = math.atan2(t3, t4)

    print('pitch:{}, yaw:{}, roll:{}'.format(pitch, yaw, roll))

    # 单位转换:将弧度转换为度
    Y = int((pitch/math.pi)*180)
    X = int((yaw/math.pi)*180)
    Z = int((roll/math.pi)*180)

    return 0, Y, X, Z
    //原文链接:https ://blog.csdn.net/u014090429/article/details/100762308
    */
    //2)旋转向量— > 四元数— > 欧拉角
    double theta = cv::norm(rotation_vector,NORM_L2);
    // transformed to quaterniond
    float w = cos(theta / 2);
    float x = sin(theta / 2) * rotation_vector.at<double>(0, 0) / theta;
    float y = sin(theta / 2) * rotation_vector.at<double>(1, 0) / theta;
    float z = sin(theta / 2) * rotation_vector.at<double>(2, 0) / theta;

    float ysqr = y * y;

    // pitch(x - axis rotation)
    float t0 = 2.0 * (w * x + y * z);
    float t1 = 1.0 - 2.0 * (x * x + ysqr);
    printf("t0 = % f, t1 = % f\n", t0, t1);
    float pitch = atan2(t0, t1);

    // yaw(y - axis rotation)
    float t2 = 2.0 * (w * y - z * x);
    if (t2 > 1.0)
    {
        t2 = 1.0;
    }
    if (t2 < -1.0)
    {
        t2 = -1.0;
    }

    float yaw = asin(t2);

    // roll(z - axis rotation)
    float t3 = 2.0 * (w * z + x * y);
    float t4 = 1.0 - 2.0 * (ysqr + z * z);
    float roll = atan2(t3, t4);

    printf("pitch =%f, yaw =%f,roll =%f\n", pitch, yaw, roll);

    // 单位转换:将弧度转换为度
    float Y = float((pitch / CV_PI) * 180);
    float X = float((yaw / CV_PI) * 180);
    float Z = float((roll / CV_PI) * 180);
    if (X > 90)
    {
        X = (X - 180);
    }
    if (X < -90)
    {
        X = (X + 180);
    }
    
    if (Y > 90)
    {
        Y = (Y - 180);
    }
    if (Y < -90)
    {
        Y = (Y + 180);
    }

    if (Z > 90)
    {
        Z = (Z - 180) ;
    }
    if (Z < -90)
    {
        Z = (Z + 180) ;
    }
    facePose.push_back(X);
    facePose.push_back(Y);
    facePose.push_back(Z);
    printf("X =%f, Y =%f,Z =%f\n", X, Y, Z);

     //method2
   /* float X1 = getYaw(landmarks[2].x,0,img_face.cols);
    float Y1 = getPitch(landmarks[2].y,0, img_face.rows);*/
    float X1 = getYaw(landmarks[2].x, 503, 38);
    float Y1 = getPitch(landmarks[2].y, 194, 61); 
    float Z1 = getRoll(landmarks[0].x, landmarks[0].y, landmarks[1].x, landmarks[1].y);
    printf("X1 =%f, Y1 =%f,Z1 =%f\n", X1, Y1, Z1);
   
    //method3
    cv::Mat rotateMat; // 旋转向量
    cv::Rodrigues(rotation_vector, rotateMat); // 转换为旋转矩阵
    cv::Mat proj_matrix;
    cv::hconcat(rotateMat, translation_vector, proj_matrix);
    cv::Mat euler_angle = cv::Mat(3, 1, CV_64FC1);
    //temp buf for decomposeProjectionMatrix()
    cv::Mat out_intrinsics = cv::Mat(3, 3, CV_64FC1);
    cv::Mat out_rotation = cv::Mat(3, 3, CV_64FC1);
    cv::Mat out_translation = cv::Mat(3, 1, CV_64FC1);

    cv::Mat R, t, S;
    cv::decomposeProjectionMatrix(proj_matrix, out_intrinsics, out_rotation, out_translation, cv::noArray(), cv::noArray(), cv::noArray(), euler_angle);
    float X2= euler_angle.at<double>(0);
    float Y2 = euler_angle.at<double>(1);
    float Z2 = euler_angle.at<double>(2);
    if (X2 > 90)
    {
        X2 = (X2 - 180);
    }
    if (X2 < -90)
    {
        X2 = (X2 + 180);
    }

    if (Y2 > 90)
    {
        Y2 = (Y2 - 180);
    }
    if (Y2 < -90)
    {
        Y2 = (Y2 + 180);
    }

    if (Z2 > 90)
    {
        Z2 = (Z2 - 180);
    }
    if (Z2 < -90)
    {
        Z2 = (Z2 + 180);
    }
   // matrix2angle(rotateMat,X2,Y2,Z2);
    printf("X2 =%f, Y2 =%f,Z2 =%f\n", X2, Y2, Z2);
    return facePose;
}
void test_getFacePoseByLandmark()
{
    cv::Mat image = cv2_imread("1.jpg");
   
    std::vector<cv::Point> landmarks;
    //1.jpg
    
    landmarks.push_back(cv::Point(90,318));
    landmarks.push_back(cv::Point(178, 317));
    landmarks.push_back(cv::Point(130, 365));
    landmarks.push_back(cv::Point(97, 407));
    landmarks.push_back(cv::Point(160, 406));
    FacePts pts,outpts;
    pts.x[0] = 90; pts.y[0] = 318;
    pts.x[1] = 178; pts.y[1] = 317;
    pts.x[2] = 130; pts.y[2] = 365;
    pts.x[3] = 97; pts.y[3] = 407;
    pts.x[4] = 160; pts.y[4] = 406;
    bool pose = getFacePose(pts);
    printf("pose:%d\n", pose);
    cv::Mat alignimg = Align_and_CropFace(image, pts, outpts);
    cv::imshow("align", alignimg);
    cv::waitKey(0);
   //11.jpg
    
 /*  landmarks.push_back(cv::Point(50,92));
   landmarks.push_back(cv::Point(138, 93));
   landmarks.push_back(cv::Point(96, 140));
   landmarks.push_back(cv::Point(65, 179));
   landmarks.push_back(cv::Point(124, 180));*/
   
    //33.jpg -1
    
 /*   landmarks.push_back(cv::Point(221, 245));
    landmarks.push_back(cv::Point(229, 233));
    landmarks.push_back(cv::Point(235, 238));
    landmarks.push_back(cv::Point(232, 263));
    landmarks.push_back(cv::Point(240, 252));
    FacePts pts, outpts;
    pts.x[0] = 221; pts.y[0] = 245;
    pts.x[1] = 229; pts.y[1] = 233;
    pts.x[2] = 235; pts.y[2] = 238;
    pts.x[3] = 232; pts.y[3] = 263;
    pts.x[4] = 240; pts.y[4] = 252;
    bool pose = getFacePose(pts);
    printf("pose:%d\n", pose);
    cv::Mat alignimg = Align_and_CropFace(image, pts, outpts);
    cv::imshow("align", alignimg);
    cv::waitKey(0);*/ 
     33.jpg -2
    /*landmarks.push_back(cv::Point(509, 209));
    landmarks.push_back(cv::Point(524, 227));
    landmarks.push_back(cv::Point(511, 227));
    landmarks.push_back(cv::Point(507, 239));
    landmarks.push_back(cv::Point(516, 243));
    FacePts pts, outpts;
    pts.x[0] = 509; pts.y[0] = 209;
    pts.x[1] = 524; pts.y[1] = 227;
    pts.x[2] = 511; pts.y[2] = 227;
    pts.x[3] = 507; pts.y[3] = 239;
    pts.x[4] = 516; pts.y[4] = 243;
    bool pose = getFacePose(pts);
    printf("pose:%d\n", pose);
    cv::Mat alignimg = Align_and_CropFace(image, pts, outpts);
    cv::imshow("align", alignimg);
    cv::waitKey(0);*/
    std::vector<float> facePose;
    facePose = getFacePose(landmarks,image);
}
int main() 
{
    test_getFacePoseByLandmark();
    //run_face_3dkps();
    return 0;
}

标签:landmarks,back,points,人脸,push,对齐,pts,cv,关键点
From: https://blog.csdn.net/u012374012/article/details/142939291

相关文章

  • 传统特征算法——人脸识别
    人脸识别是目前人工智能领域中成熟较早、落地较广的技术之一,广泛应用于手机解锁、支付验证、安防布控等多个领域。其核心在于通过特定的算法识别图像或视频中人脸的身份,这一过程的实现离不开特征算法的支持。以下是对人脸识别特征算法的详细介绍:一、人脸识别系统概述一个......
  • 【进阶OpenCV】 (17)-- Dlib库 --实现人脸检测
    文章目录Dlib库一、Dlib库安装二、实现人脸检测1.生成人脸检测器2.检测人脸3.显示人脸总结Dlib库Dlib提供了丰富的图像处理和计算机视觉工具,如面部特征检测、物体检测、图像变换等,这些工具使得开发者能够轻松地进行各种图像处理任务。一、Dlib库安装pipinst......
  • Spring Cloud Gateway关键点全局Token过滤器,局部过滤器接口耗时,全链路跟踪TraceId日志
    一.全局Token过滤器在SpringCloudGateway中,实现全局过滤器的目的是对所有进入系统的请求或响应进行统一处理,比如添加日志、鉴权等。下面是如何创建一个全局过滤器的基本步骤:步骤1:创建过滤器类首先,你需要创建一个实现了GlobalFilter接口,创建一个全局token过滤器。@Slf......
  • 安全帽人脸闸机联动系统
    安全帽人脸闸机联动系统基于人员进出工地的安全管理创新解决方案。安全帽人脸闸机联动系统结合了安全帽和工装穿戴检测以及人脸识别技术,安全帽人脸闸机联动系统通过对人员进行安全帽和工装穿戴的检测,并使用人脸识别技术判断其是否为工作人员,从而实现对工地出入口的控制和管理。安......
  • 【进阶OpenCV】 (14)-- 人脸识别 -- LBPH 算法
    文章目录LBPH算法一、基本思想二、LBPH算法步骤1.图像划分2.局部二值模式特征提取3.直方图统计4.特征向量生成5.相似度计算三、代码实现1.图像预处理2.创建一个LBPH的人脸识别器3.训练实例模型4.图像预测总结LBPH算法**LBPH(LocalBinaryPatternsHis......
  • 金农对齐白石绘画的影响
    金农对齐白石绘画的影响雷家林      人们对于齐白石绘画晚年受吴昌硕的影响关注深入点,对于其受清代大家金农地影响深入理解的不多,客观点来说,吴氏对齐氏的影响还只是表层的,外在的,更多的是合于近现代的时代风尚,或者笔墨当随时代,这是过去常常说的一句有关艺术的套话......
  • 《C++内存对齐策略:提升性能的关键之路》
    在C++编程的广阔世界中,高效的内存对齐策略是一个至关重要却常常被忽视的主题。它不仅影响着程序的性能,还关系到内存的使用效率和稳定性。今天,我们就来深入探讨一下如何在C++中实现高效的内存对齐策略。一、为什么内存对齐如此重要?内存对齐在C++中具有重大意义。首先,它......
  • 《OpenCV计算机视觉》—— 人脸检测
    文章目录一、人脸检测流程介绍二、用于人脸检测的关键方法1.加载分类器(cv2.CascadeClassifier())2.检测图像中的人脸(cv2.CascadeClassifier.detectMultiscale())三、代码实现一、人脸检测流程介绍下面是一张含有多个人脸的图片第一步:读取图片后将图片转换成灰度图第......
  • 人脸识别调研
    项目列表开源项目语言/环境准确率(onLabeledFacesintheWild)备注ageitgey/face_recognitionPython,Dlib99.38%DocsDFacePython  facenetTensorFlow99.2%https://mp.weixin.qq.com/s/1kgbYScIujSjCRvfPGw0tgV......
  • 安全帽穿戴检测人脸闸机联动系统
    安全帽穿戴检测人脸闸机联动系统结合安全帽穿戴检测技术和人脸识别技术,安全帽穿戴检测人脸闸机联动系统实现对进入工地施工区域人员是否穿戴安全帽进行精准监测和身份识别,安全帽穿戴检测人脸闸机联动系统通过摄像头对人员进行安全帽穿戴检测和人脸识别,只有在满足这两个条件的情况......