Ubuntu下基于opencv和qt的人脸识别考勤系统

完整项目地址:https://download.csdn.net/download/lijunhcn/88628829

本项目是Ubuntu下基于opencv和qt的人脸识别考勤系统。
相关项目文档:
项目结构:
model:

部分核心源码:

#include "mtcnn.h"

using namespace std;
using namespace cv;

bool cmpScore(orderScore lsh, orderScore rsh) {
    if (lsh.score < rsh.score)
        return true;
    else
        return false;
}

mtcnn::mtcnn()
{
    std::string param1 = "model/mtcnn1.param";
    std::string model1 = "model/mtcnn1.bin";
    std::string param2 = "model/mtcnn2.param";
    std::string model2 = "model/mtcnn2.bin";
    std::string param3 = "model/mtcnn3.param";
    std::string model3 = "model/mtcnn3.bin";
    Pnet.load_param(param1.c_str());
    Pnet.load_model(model1.c_str());
    Rnet.load_param(param2.c_str());
    Rnet.load_model(model2.c_str());
    Onet.load_param(param3.c_str());
    Onet.load_model(model3.c_str());
}

void mtcnn::generateBbox(ncnn::Mat score, ncnn::Mat location, std::vector<Bbox>& boundingBox_, std::vector<orderScore>& bboxScore_, float scale) {
    int stride = 2;
    int cellsize = 12;
    int count = 0;
    //score p
    float* p = score.channel(1);
    float* plocal = location.channel(0);
    Bbox bbox;
    orderScore order;
    for (int row = 0;row < score.h;row++) {
        for (int col = 0;col < score.w;col++) {
            if (*p > threshold[0]) {
                bbox.score = *p;
                order.score = *p;
                order.oriOrder = count;
                bbox.x1 = round((stride * col + 1) / scale);
                bbox.y1 = round((stride * row + 1) / scale);
                bbox.x2 = round((stride * col + 1 + cellsize) / scale);
                bbox.y2 = round((stride * row + 1 + cellsize) / scale);
                bbox.exist = true;
                bbox.area = (bbox.x2 - bbox.x1) * (bbox.y2 - bbox.y1);
                for (int channel = 0;channel < 4;channel++)
                    bbox.regreCoord[channel] = location.channel(channel)[0];
                boundingBox_.push_back(bbox);
                bboxScore_.push_back(order);
                count++;
            }
            p++;
            plocal++;
        }
    }
}
void mtcnn::nms(std::vector<Bbox>& boundingBox_, std::vector<orderScore>& bboxScore_, const float overlap_threshold, string modelname) {
    if (boundingBox_.empty()) {
        return;
    }
    std::vector<int> heros;
    //sort the score
    sort(bboxScore_.begin(), bboxScore_.end(), cmpScore);

    int order = 0;
    float IOU = 0;
    float maxX = 0;
    float maxY = 0;
    float minX = 0;
    float minY = 0;
    while (bboxScore_.size() > 0) {
        order = bboxScore_.back().oriOrder;
        bboxScore_.pop_back();
        if (order < 0)continue;
        if (boundingBox_.at(order).exist == false) continue;
        heros.push_back(order);
        boundingBox_.at(order).exist = false;//delete it

        for (int num = 0;num < boundingBox_.size();num++) {
            if (boundingBox_.at(num).exist) {
                //the iou
                maxX = (boundingBox_.at(num).x1 > boundingBox_.at(order).x1) ? boundingBox_.at(num).x1 : boundingBox_.at(order).x1;
                maxY = (boundingBox_.at(num).y1 > boundingBox_.at(order).y1) ? boundingBox_.at(num).y1 : boundingBox_.at(order).y1;
                minX = (boundingBox_.at(num).x2 < boundingBox_.at(order).x2) ? boundingBox_.at(num).x2 : boundingBox_.at(order).x2;
                minY = (boundingBox_.at(num).y2 < boundingBox_.at(order).y2) ? boundingBox_.at(num).y2 : boundingBox_.at(order).y2;
                //maxX1 and maxY1 reuse
                maxX = ((minX - maxX + 1) > 0) ? (minX - maxX + 1) : 0;
                maxY = ((minY - maxY + 1) > 0) ? (minY - maxY + 1) : 0;
                //IOU reuse for the area of two bbox
                IOU = maxX * maxY;
                if (!modelname.compare("Union"))
                    IOU = IOU / (boundingBox_.at(num).area + boundingBox_.at(order).area - IOU);
                else if (!modelname.compare("Min")) {
                    IOU = IOU / ((boundingBox_.at(num).area < boundingBox_.at(order).area) ? boundingBox_.at(num).area : boundingBox_.at(order).area);
                }
                if (IOU > overlap_threshold) {
                    boundingBox_.at(num).exist = false;
                    for (vector<orderScore>::iterator it = bboxScore_.begin(); it != bboxScore_.end();it++) {
                        if ((*it).oriOrder == num) {
                            (*it).oriOrder = -1;
                            break;
                        }
                    }
                }
            }
        }
    }
    for (int i = 0;i < heros.size();i++)
        boundingBox_.at(heros.at(i)).exist = true;
}
void mtcnn::refineAndSquareBbox(vector<Bbox>& vecBbox, const int& height, const int& width) {
    if (vecBbox.empty()) {
        cout << "Bbox is empty!!" << endl;
        return;
    }
    float bbw = 0, bbh = 0, maxSide = 0;
    float h = 0, w = 0;
    float x1 = 0, y1 = 0, x2 = 0, y2 = 0;
    for (vector<Bbox>::iterator it = vecBbox.begin(); it != vecBbox.end();it++) {
        if ((*it).exist) {
            bbw = (*it).x2 - (*it).x1 + 1;
            bbh = (*it).y2 - (*it).y1 + 1;
            x1 = (*it).x1 + (*it).regreCoord[0] * bbw;
            y1 = (*it).y1 + (*it).regreCoord[1] * bbh;
            x2 = (*it).x2 + (*it).regreCoord[2] * bbw;
            y2 = (*it).y2 + (*it).regreCoord[3] * bbh;

            w = x2 - x1 + 1;
            h = y2 - y1 + 1;

            maxSide = (h > w) ? h : w;
            x1 = x1 + w * 0.5 - maxSide * 0.5;
            y1 = y1 + h * 0.5 - maxSide * 0.5;
            (*it).x2 = round(x1 + maxSide - 1);
            (*it).y2 = round(y1 + maxSide - 1);
            (*it).x1 = round(x1);
            (*it).y1 = round(y1);

            //boundary check
            if ((*it).x1 < 0)(*it).x1 = 0;
            if ((*it).y1 < 0)(*it).y1 = 0;
            if ((*it).x2 > width)(*it).x2 = width - 1;
            if ((*it).y2 > height)(*it).y2 = height - 1;

            it->area = (it->x2 - it->x1) * (it->y2 - it->y1);
        }
    }
}

void mtcnn::detect(ncnn::Mat& img_, std::vector<Bbox>& finalBbox_) {
    firstBbox_.clear();
    firstOrderScore_.clear();
    secondBbox_.clear();
    secondBboxScore_.clear();
    thirdBbox_.clear();
    thirdBboxScore_.clear();

    img = img_;
    img_w = img.w;
    img_h = img.h;
    img.substract_mean_normalize(mean_vals, norm_vals);//归一化

    float minl = img_w < img_h ? img_w : img_h;
    int MIN_DET_SIZE = 12;
    int minsize = 90;
    float m = (float)MIN_DET_SIZE / minsize;
    minl *= m;
    float factor = 0.709;
    int factor_count = 0;
    vector<float> scales_;//存放一些缩小系数?
    //确保图片大小大于最小探测大小???
    while (minl > MIN_DET_SIZE) {
        if (factor_count > 0)m = m * factor;
        scales_.push_back(m);
        minl *= factor;
        factor_count++;
    }
    orderScore order;
    int count = 0;

    for (size_t i = 0; i < scales_.size(); i++) {
        int hs = (int)ceil(img_h * scales_[i]);
        int ws = (int)ceil(img_w * scales_[i]);
        //ncnn::Mat in = ncnn::Mat::from_pixels_resize(image_data, ncnn::Mat::PIXEL_RGB2BGR, img_w, img_h, ws, hs);
        ncnn::Mat in;
        resize_bilinear(img_, in, ws, hs);
        //in.substract_mean_normalize(mean_vals, norm_vals);
        ncnn::Extractor ex = Pnet.create_extractor();
        ex.set_light_mode(true);
        ex.input("data", in);
        ncnn::Mat score_, location_;
        ex.extract("prob1", score_);
        ex.extract("conv4-2", location_);
        std::vector<Bbox> boundingBox_;
        std::vector<orderScore> bboxScore_;
        generateBbox(score_, location_, boundingBox_, bboxScore_, scales_[i]);
        nms(boundingBox_, bboxScore_, nms_threshold[0]);

        for (vector<Bbox>::iterator it = boundingBox_.begin(); it != boundingBox_.end();it++) {
            if ((*it).exist) {
                firstBbox_.push_back(*it);
                order.score = (*it).score;
                order.oriOrder = count;
                firstOrderScore_.push_back(order);
                count++;
            }
        }
        bboxScore_.clear();
        boundingBox_.clear();
    }
    //the first stage's nms
    if (count < 1)return;
    nms(firstBbox_, firstOrderScore_, nms_threshold[0]);
    refineAndSquareBbox(firstBbox_, img_h, img_w);

    //second stage
    count = 0;
    for (vector<Bbox>::iterator it = firstBbox_.begin(); it != firstBbox_.end();it++) {
        if ((*it).exist) {
            ncnn::Mat tempIm;
            copy_cut_border(img, tempIm, (*it).y1, img_h - (*it).y2, (*it).x1, img_w - (*it).x2);
            ncnn::Mat in;
            resize_bilinear(tempIm, in, 24, 24);
            ncnn::Extractor ex = Rnet.create_extractor();
            ex.set_light_mode(true);
            ex.input("data", in);
            ncnn::Mat score, bbox;
            ex.extract("prob1", score);
            ex.extract("conv5-2", bbox);
            if ((score[1]) > threshold[1]) {
                for (int channel = 0;channel < 4;channel++)
                    it->regreCoord[channel] = bbox[channel];
                it->area = (it->x2 - it->x1) * (it->y2 - it->y1);
                it->score = score[1];
                secondBbox_.push_back(*it);
                order.score = it->score;
                order.oriOrder = count++;
                secondBboxScore_.push_back(order);
            }
            else {
                (*it).exist = false;
            }
        }
    }
    //printf("secondBbox_.size()=%ld\n", secondBbox_.size());
    if (count < 1)return;
    nms(secondBbox_, secondBboxScore_, nms_threshold[1]);
    refineAndSquareBbox(secondBbox_, img_h, img_w);

    //third stage
    count = 0;
    for (vector<Bbox>::iterator it = secondBbox_.begin(); it != secondBbox_.end();it++) {
        if ((*it).exist) {
            ncnn::Mat tempIm;
            copy_cut_border(img, tempIm, (*it).y1, img_h - (*it).y2, (*it).x1, img_w - (*it).x2);
            ncnn::Mat in;
            resize_bilinear(tempIm, in, 48, 48);
            ncnn::Extractor ex = Onet.create_extractor();
            ex.set_light_mode(true);
            ex.input("data", in);
            ncnn::Mat score, bbox, keyPoint;
            ex.extract("prob1", score);
            ex.extract("conv6-2", bbox);
            ex.extract("conv6-3", keyPoint);
            if (score[1] > threshold[2]) {
                for (int channel = 0;channel < 4;channel++)
                    it->regreCoord[channel] = bbox[channel];
                it->area = (it->x2 - it->x1) * (it->y2 - it->y1);
                it->score = score[1];
                for (int num = 0;num < 5;num++) {
                    (it->ppoint)[num] = it->x1 + (it->x2 - it->x1) * keyPoint[num];
                    (it->ppoint)[num + 5] = it->y1 + (it->y2 - it->y1) * keyPoint[num + 5];
                }

                thirdBbox_.push_back(*it);
                order.score = it->score;
                order.oriOrder = count++;
                thirdBboxScore_.push_back(order);
            }
            else
                (*it).exist = false;
        }
    }

    //printf("thirdBbox_.size()=%ld\n", thirdBbox_.size());
    if (count < 1)return;
    refineAndSquareBbox(thirdBbox_, img_h, img_w);
    nms(thirdBbox_, thirdBboxScore_, nms_threshold[2], "Min");
    finalBbox_ = thirdBbox_;
}

std::vector<Bbox> detect_mtcnn(const cv::Mat& cv_img)
{
    mtcnn mm;
    ncnn::Mat ncnn_img = ncnn::Mat::from_pixels(cv_img.data, ncnn::Mat::PIXEL_BGR2RGB, cv_img.cols, cv_img.rows);
    std::vector<Bbox> finalBbox;
    mm.detect(ncnn_img, finalBbox);
    return finalBbox;
}
  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明 基于Qt的系统项目开发 课程设计 毕业设计 供参考 源代码+说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

辣椒种子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值