zuoqing1988 / ZQCNN

一款推理框架,同时有很多有用的demo,觉得好用请点星啊
MIT License
2.22k stars 508 forks source link

ZQ_FaceDetectorMTCNN检测失败的问题 #137

Open canyuedao opened 4 years ago

canyuedao commented 4 years ago

左博您好!我遇到一个问题,在一次性检测很多张图片时,发现有不少检测失败的图片。

  1. 然后我用您代码里的例子程序对失败的图片进行单张检测,发现是可以检测成功的。
  2. 接着我写了下面的测试程序对两张图片做循环检测,结果发现有的图片是没有问题一直都是两张检测出来都有人脸,而换了图片之后,刚开始两张图片都是可以检查出人脸的,而每隔一段间隔之后就会出现一张图片没有检测出人脸的情况,接着又是好的两张都有人脸。而且这个间隔根据图片的不同也有所不同,而且同样的两张图片每两次失败的间隔也是不同的,但重启程序同样的两张图片,每次失败的地方都是一样的。
  3. 但是当我每次检测的时候把ZQ_FaceDetectorMTCNN和ZQ_FaceRecognizerArcFaceZQCNN对象都释放了再重新创建就不会有这个问题,我想这是不是程序变量没有重设引起的?我检查了代码,但是能力所限没有找出问题所在,不知左博您能不能给看一下,下面是我的测试代码:
#include <QCoreApplication>
#include <QDir>
#include <iostream>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <opencv2/imgproc/imgproc_c.h>
#include "ZQ_FaceDetectorMTCNN.h"
#include "ZQ_FaceDetectorLibFaceDetect.h"
#include "ZQ_FaceRecognizerArcFaceZQCNN.h"
#include "ZQ_CNN_CompileConfig.h"
#if ZQ_CNN_USE_BLAS_GEMM
#include <openblas/cblas.h>
#elif ZQ_CNN_USE_MKL_GEMM
#include <mkl/mkl.h>
#endif

#include <vector>
#include <string>
#include <iostream>
#include <algorithm>

using namespace ZQ;
using namespace cv;
using namespace std;

#define THREAD_NUM 2

int main(int argc, char *argv[])
{
#if ZQ_CNN_USE_BLAS_GEMM
#define USE_OPENMP=1
    openblas_set_num_threads(THREAD_NUM);
#elif ZQ_CNN_USE_MKL_GEMM
    mkl_set_num_threads(THREAD_NUM);
#endif

    QCoreApplication a(argc, argv);

    ZQ_FaceDetectorMTCNN* mtcnn = NULL;
    ZQ_FaceRecognizerArcFaceZQCNN* recognizer = NULL;

    mtcnn = new ZQ_FaceDetectorMTCNN();
    if (!mtcnn->Init("model", THREAD_NUM))
    {
        printf("failed to init mtcnn\n");
        return -1;
    }

    std::string prototxt_file = "model/model-r100-am.zqparams";
    std::string caffemodel_file = "model/model-r100-am.nchwbin";
    std::string out_blob_name = "fc5";
    recognizer = new ZQ_FaceRecognizerArcFaceZQCNN();
    if (!recognizer->Init("", prototxt_file, caffemodel_file, out_blob_name))
    {
        printf("failed to init arcface\n");
        return -1;
    }

    //load image

    int iFaildCount = 0;
    int iTotalDetect = 0;
    while(1)
    {
        long t0 = cv::getTickCount();
        iTotalDetect++;
        if((iTotalDetect % 100) == 0)
        {
            printf("iTotalDetect=%d\n", iTotalDetect);
        }

        cv::Mat gallery_img_color = cv::imread("./1_1574162867.jpeg", 1);
        cv::Mat probe_img_color = cv::imread("./1_1574162975.jpeg", 1);

        long t1 = cv::getTickCount();
        double secs = (t1 - t0)/cv::getTickFrequency();

        cout << "load image takes " << secs << " seconds " << endl;

        // Detect faces
        vector<ZQ_CNN_BBox> gallery_faces;
        if (!mtcnn->FindFaceROI(gallery_img_color.data, gallery_img_color.cols, gallery_img_color.rows, gallery_img_color.step[0], ZQ_PIXEL_FMT_BGR,
            0.1, 0.1, 0.9, 0.9, 40, 0.709, gallery_faces))
        {
            printf("failed to find face using MTCNN\n");
            continue;
        }
        int32_t gallery_face_num = gallery_faces.size();

        vector<ZQ_CNN_BBox> probe_faces;
        if (!mtcnn->FindFaceROI(probe_img_color.data, probe_img_color.cols, probe_img_color.rows, probe_img_color.step[0], ZQ_PIXEL_FMT_BGR,
            0.1, 0.1, 0.9, 0.9, 40, 0.709, probe_faces))
        {
            printf("failed to find face using MTCNN\n");
            continue;
        }
        int32_t probe_face_num = probe_faces.size();

        cout << "gallery_face_num:" << gallery_face_num << " probe_face_num:" << probe_face_num << endl;

        if (gallery_face_num == 0 || probe_face_num==0)
        {
          std::cout << "Faces are not detected." << "gallery_face_num:" << gallery_face_num << " probe_face_num:" << probe_face_num << " total failed:" << ++iFaildCount
                    << " iTotalDetect:" << iTotalDetect << endl;
          continue;
        }

        cout << "gallery_face_num:" << gallery_face_num << " x:" << gallery_faces[0].col1 << " y:" <<
             gallery_faces[0].row1 << " width:" << gallery_faces[0].col2 - gallery_faces[0].col1 << " height:" << gallery_faces[0].row2 - gallery_faces[0].row1 <<
             " score:" << gallery_faces[0].score << endl;
        cout << "probe_face_num:" << probe_face_num << " x:" << probe_faces[0].col1 << " y:" <<
             probe_faces[0].row1 << " width:" << probe_faces[0].col2 - probe_faces[0].col1 << " height:" << probe_faces[0].row2 - probe_faces[0].row1 <<
             " score:" << probe_faces[0].score << endl;

        t0 = cv::getTickCount();
        secs = (t0 - t1)/cv::getTickFrequency();

        cout << "Detect faces takes " << secs << " seconds " << endl;

        // Detect 5 facial landmarks

        int crop_width = recognizer->GetCropWidth();
        int crop_height = recognizer->GetCropHeight();
        cv::Mat cropgallery(crop_height, crop_width, CV_MAKETYPE(8, 3));
        recognizer->CropImage(gallery_img_color.data, gallery_img_color.cols, gallery_img_color.rows, gallery_img_color.step[0], ZQ_PIXEL_FMT_BGR, gallery_faces[0].ppoint, gallery_faces[0].ppoint + 5, cropgallery.data, cropgallery.step[0]);

        cv::Mat cropprobe(crop_height, crop_width, CV_MAKETYPE(8, 3));
        recognizer->CropImage(probe_img_color.data, probe_img_color.cols, probe_img_color.rows, probe_img_color.step[0], ZQ_PIXEL_FMT_BGR, probe_faces[0].ppoint, probe_faces[0].ppoint + 5, cropprobe.data, cropprobe.step[0]);

        for (int i = 0; i<5; i++)
        {
          cv::circle(gallery_img_color, cv::Point((int)gallery_faces[0].ppoint[i], (int)gallery_faces[0].ppoint[i+5]), 2,
            CV_RGB(0, 255, 0));
          cv::circle(probe_img_color, cv::Point((int)probe_faces[0].ppoint[i], (int)probe_faces[0].ppoint[i+5]), 2,
            CV_RGB(0, 255, 0));
        }
        cv::imwrite("gallery_point_result.jpg", gallery_img_color);
        cv::imwrite("probe_point_result.jpg", probe_img_color);

        t1 = cv::getTickCount();
        secs = (t1 - t0)/cv::getTickFrequency();

        cout << "Detect 5 facial landmarks takes " << secs << " seconds " << endl;

        // Extract face identity feature
        int feat_dim = recognizer->GetFeatDim();
        float* gallery_fea = new float[feat_dim];
        float* probe_fea = new float[feat_dim];
        recognizer->ExtractFeature(cropgallery.data, cropgallery.step[0], ZQ_PIXEL_FMT_BGR, gallery_fea, true);
        recognizer->ExtractFeature(cropprobe.data, cropprobe.step[0], ZQ_PIXEL_FMT_BGR, probe_fea, true);

        std::cout << "feature len:" << feat_dim << endl;

        t0 = cv::getTickCount();
        secs = (t0 - t1)/cv::getTickFrequency();

        cout << "Extract face identity feature takes " << secs << " seconds " << endl;

        // Caculate similarity of two faces
        float sim = recognizer->CalSimilarity(gallery_fea, probe_fea);
        std::cout << "score:" << sim <<endl;

        t1 = cv::getTickCount();

        secs = (t1 - t0)/cv::getTickFrequency();

        cout << "Caculate similarity of two faces takes " << secs << " seconds " << endl << endl;

        delete gallery_fea;
        delete probe_fea;
    }

    return a.exec();
}
zuoqing1988 commented 4 years ago

加我QQ 275918592

zuoqing1988 commented 4 years ago

先改掉基础错误: delete gallery_fea -- >delete []gallery_fea delete probe_fea --> delete []prob_fea

canyuedao commented 4 years ago

先改掉基础错误: delete gallery_fea -- >delete []gallery_fea delete probe_fea --> delete []prob_fea

好的,我加了,您通过一下

zuoqing1988 commented 4 years ago

提醒后来人: 将ChangeSize函数里的memset取掉注释