美文网首页
OpenCV 人脸识别

OpenCV 人脸识别

作者: rome753 | 来源:发表于2022-05-17 22:03 被阅读0次

    1 CascadeClassifier 级联分类器人脸识别

    有两种:haar级联和lbp级联,我用brew安装的,级联文件在/opt/homebrew/Cellar/opencv/4.5.5_2/share/opencv4/haarcascades里面,haar级联文件大小是900kb左右,lbp级联文件大小是50kb左右。
    检测前需要将图像转化成灰度图,并做直方图均衡化处理。

    lbp的文件大小、识别速度和效果都要好于haar。

    总的来说,人脸检测效果很一般,人脸不动时检测框会闪烁,人脸稍有偏转或遮挡就检测不到。

    int myFaceDetect(int argc, char** argv) {
        double w = 0, h = 0, fps = 24;
        Mat frame;
        Mat gray;
        Mat res;
        VideoCapture cap;
        
        if (!cap.open(0)) {
            return 0;
        }
        w = cap.get(CAP_PROP_FRAME_WIDTH);
        h = cap.get(CAP_PROP_FRAME_HEIGHT);
        
        printf("cap w: %f, h: %f\n", w, h);
        
        namedWindow("cam");
        while(true) {
            auto tick = getTickCount();
    //        cap >> frame;
            cap.read(frame);
            if (frame.empty()) {
                break;
            }
            flip(frame, frame, 1);
            cvtColor(frame, gray, COLOR_BGRA2GRAY);
            equalizeHist(gray, gray);
            
    //        auto ccPath = "/opt/homebrew/Cellar/opencv/4.5.5_2/share/opencv4/haarcascades/haarcascade_frontalface_extended.xml";
            auto ccPath = "/opt/homebrew/Cellar/opencv/4.5.5_2/share/opencv4/lbpcascades/lbpcascade_frontalface_improved.xml";
            CascadeClassifier cc;
            if (!cc.load(ccPath)) {
                cout << "load CascadeClassifier failed" << endl;
                return -1;
            }
            vector<Rect> faces;
            cc.detectMultiScale(gray, faces);
            for (int i = 0; i < faces.size(); i++) {
                rectangle(frame, faces[i], Scalar(0, 0, 255));
            }
            imshow("cam", frame);
            auto time = (getTickCount() - tick) / getTickFrequency();
            printf("handleTime: %f\n", time);
            
            if (waitKey(1000 / fps) == ' ') {
                break;
            }
        }
        destroyAllWindows();
        return 0;
    }
    

    2 DNN 深度神经网络人脸识别

    需要下载神经网络模型描述文件,模型大小为2.7Mb,描述文件大小为35kb

    OpenCV的dnn支持caffe和TensorFlow两种模型,我这里用的是TensorFlow的模型。

    检测直接用原始图像就行。

    人脸检测效果非常好,人脸偏转或者遮挡一半仍能检测到。缺点是计算时间长一点,在移动端会明显一点。

    int myDnnFaceDetect(int argc, char** argv) {
        double w = 0, h = 0, fps = 24;
        Mat frame;
        Mat gray;
        Mat res;
        VideoCapture cap;
        
        if (!cap.open(0)) {
            return 0;
        }
        w = cap.get(CAP_PROP_FRAME_WIDTH);
        h = cap.get(CAP_PROP_FRAME_HEIGHT);
        
        printf("cap w: %f, h: %f\n", w, h);
        
        auto pb_path = "/Users/chenrongchao/Downloads/face_detector-main/opencv_face_detector_uint8.pb";
        auto pbtext_path = "/Users/chenrongchao/Downloads/face_detector-main/opencv_face_detector.pbtxt";
        dnn::Net net = dnn::readNetFromTensorflow(pb_path, pbtext_path);
        
        namedWindow("cam");
        while(true) {
            auto tick = getTickCount();
    //        cap >> frame;
            cap.read(frame);
            if (frame.empty()) {
                break;
            }
            flip(frame, frame, 1);
    //        cvtColor(frame, gray, COLOR_BGRA2GRAY);
            
            auto blob = dnn::blobFromImage(frame, 1.0, Size2i(300, 300), Scalar(104,177,123),false,false);
            net.setInput(blob);
            auto probs = net.forward();
            Mat detectionMat(probs.size[2], probs.size[3], CV_32F, probs.ptr<float>());
            //解析结果
            for (int i = 0; i < detectionMat.rows; i++) {
                float confidence = detectionMat.at<float>(i, 2);
                if (confidence > 0.5) { //提取矩形四个角的坐标
                    int x1 = static_cast<int>(detectionMat.at<float>(i, 3)*frame.cols);
                    int y1 = static_cast<int>(detectionMat.at<float>(i, 4)*frame.rows);
                    int x2 = static_cast<int>(detectionMat.at<float>(i, 5)*frame.cols);
                    int y2 = static_cast<int>(detectionMat.at<float>(i, 6)*frame.rows);
                    Rect box(x1, y1, x2 - x1, y2 - y1); //红色矩形框
                    rectangle(frame, box, Scalar(0, 0, 255), 4, 8, 0); //标记人脸
                }
            }
            imshow("cam", frame);
            auto time = (getTickCount() - tick) / getTickFrequency();
            printf("handleTime: %f\n", time);
            
            if (waitKey(1000 / fps) == ' ') {
                break;
            }
        }
        destroyAllWindows();
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:OpenCV 人脸识别

          本文链接:https://www.haomeiwen.com/subject/lziburtx.html