背景

由于工作需要,研究了一下opencv,dlib人脸识别、人脸特征提取,这里做一下记录。

环境

Cmake :3.15

Qt :5.12.12(MinGW 7.3.0)

opencv,dlib的编译可以参考网上的较长,这里不罗嗦了

opencv用于人脸识别

dlib用于人脸特征提取,和特征对比(判断是否是用同一个人)

几个关键方法实现

opencv

// 获取人脸识别后的图片
cv::Mat cvFindFace(std::string face_path){
    std::string face_file = cv::samples::findFile(face_path);
    cv::Mat image = cv::imread(face_file);
    if (image.empty()) {
        std::cerr << "Could not open or find the image" << std::endl;
        return image;
    }
    std::vector<cv::Rect> faces;
    faceCascade.detectMultiScale(image, faces, 1.1, 2, cv::CASCADE_FIND_BIGGEST_OBJECT | cv::CASCADE_DO_ROUGH_SEARCH, cv::Size(30, 30));
    for (size_t i = 0; i < faces.size(); i++) {
        cv::Rect roi(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
        cv::rectangle(image, roi, cv::Scalar(255, 0, 0), 2);
    }
    return image;
}
// 将cv::Mat转为Qt的QPixmap,用于显示
void FaceRegisterDialog::slotBtnSelectPic(){
    file_path_ = "";
    QPixmap pixmap;
    ui->label->setPixmap(pixmap);
    QString filePath = QFileDialog::getOpenFileName(nullptr, QObject::tr("选择图片"),
                                                    QDir::homePath(), QObject::tr("Images (*.jpg *.png)"));
    if (!filePath.isEmpty()) {
        file_path_ = filePath;
        cv::Mat image = lx_opencv::cvFindFace(filePath.toStdString());
        QImage qImage = cvMat2QImage(image);
        pixmap = QPixmap::fromImage(qImage);
        pixmap = pixmap.scaled(ui->label->size(),Qt::KeepAspectRatio);
        ui->label->setPixmap(pixmap);
    }
}
QImage FaceRegisterDialog::cvMat2QImage(const cv::Mat &mat){
    QImage image;
        int temp = mat.type();
        switch(temp )
        {
        case CV_8UC1:
            image = QImage((const unsigned char*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_Grayscale8);
            break;
        case CV_8UC3:
            image = QImage((const unsigned char*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
            image = image.rgbSwapped();
            break;
        case CV_8UC4:
            image = QImage((const unsigned char*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
            break;
        case CV_16UC4:
            image = QImage((const unsigned char*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGBA64);
            image = image.rgbSwapped();
            break;
        }
        return image;
}

dlib

// 人脸特征提取
std::vector<float> getFaceDescriptor(string face, int &ret) {
    std::vector<float> tz_vec;
    matrix<rgb_pixel> img;
    load_image(img, face);
    std::vector<matrix<rgb_pixel>> faces;
    for (auto face : detector(img)) {
        auto shape = sp(img, face);
        matrix<rgb_pixel> face_chip;
        extract_image_chip(img, get_face_chip_details(shape, 150, 0.25), face_chip);
        faces.push_back(move(face_chip));
    }
    if (faces.size() == 0) {
        cout << "No faces found in image!" << endl;
        ret = 1;
        return tz_vec;
    }

    if (faces.size() > 1) {
        cout << "Too many faces in image!" << endl;
        ret = 10;
        return tz_vec;
    }
    ret = 0;
    std::vector<matrix<float, 0, 1>> face_descriptors = net(faces);
    matrix<float, 0, 1> tz = face_descriptors.at(0);
    for (int i = 0; i < tz.size(); i++) {
        tz_vec.push_back(tz(i));
    }
    return tz_vec;
}

// 人脸特征对比 使用常用的欧式距离,小于某个值得时候认为是同一个人(一般默认是0.6,不过本人验证的时候误差较大,改为了0.4)
int cmpFaceTz(std::vector<float> tz1, std::vector<float> tz2) {
    matrix<float, 0, 1> m_tz1(tz1.size());
    for (size_t i = 0; i < tz1.size(); ++i) {
        m_tz1(i) = tz1[i];
    }
    matrix<float, 0, 1> m_tz2(tz2.size());
    for (size_t i = 0; i < tz2.size(); ++i) {
        m_tz2(i) = tz2[i];
    }
    double dist = length(m_tz1 - m_tz2);
    cout << "The distance between the two faces is " << dist << endl;
    if (dist < cpm_len) {
        cout << "The faces are a match." << endl;
        return 0;
    } else {
        cout << "The faces are not a match." << endl;
        return -1;
    }
}
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐