多次调用的CascadeClassifier(opencv)有什么问题

What's wrong with CascadeClassifier (opencv) that is called many time

本文关键字:什么 问题 opencv 调用 CascadeClassifier      更新时间:2023-10-16

假设:

  1. 磁盘上有N个文件需要人脸检测。

  2. 如果我在"慢"模式下做,一切都会好起来(人脸是位于其矩形的人脸(:

    for(auto mat : getMyMats()) {
       CascadeClassifier facer("haarcascade_frontalface_alt.xml");
       vector<Rect> faces;
       facer.detectMultiScale(mat, faces);
    }
    
  3. 但是,如果我试图缓存和重用CascadeClassifier——接近50%的图像被检测到非常错误——无效的位置、大小、人脸数量:

    CascadeClassifier facer("haarcascade_frontalface_alt.xml");
    for(auto mat : getMyMats()) {   
        vector<Rect> faces;
        facer.detectMultiScale(mat, faces);
     }
    

CascadeClassifier重用有什么问题Windows,OpenCV 3.0同时调试和发布版本。

要复制的示例代码:

 // compiler - opencv/include referenced
    // linker - opencv/lib referenced and 
    // opencv_core300.lib, opencv_imgproc300.lib, opencv_imgcodecs300.lib, opencv_objdetect300.lib (or world or debug libs) are referenced
    // 1.png, 2.png, 3.png, 
    #include <vector>
    #include <string>
    #include <iostream>
    #include "opencv2/opencv.hpp"
    using namespace cv;
    using namespace std;

    //count faces in load-every-time call
    int no_reuse_call() {
        int cnt = 0;
        for (auto n : { "1.png","2.png","3.png" }) {
            vector<Rect> faces{};
            CascadeClassifier facer("haarcascade_frontalface_alt.xml");
            Mat m = imread(n, CV_LOAD_IMAGE_GRAYSCALE);
            facer.detectMultiScale(m, faces, 1.1, 3, CASCADE_SCALE_IMAGE, Size(50, 50));
            cnt += faces.size(); //vector given to detectMultiScale cleared in detectMultiScale
            cout << faces[0] << endl;
        }
        for (auto n : { "1.png","2.png","3.png" }) {
            vector<Rect> faces{};
            CascadeClassifier facer("haarcascade_frontalface_alt.xml");
            Mat m = imread(n, CV_LOAD_IMAGE_GRAYSCALE);
            facer.detectMultiScale(m, faces, 1.1, 3, CASCADE_SCALE_IMAGE, Size(50, 50));
            cnt += faces.size(); //vector given to detectMultiScale cleared in detectMultiScale
            cout << faces[0] << endl;
        }
        return cnt;
    }
    //coutn faces in one-instance call
    int reuse_call() {
        int cnt = 0;
        CascadeClassifier facer("haarcascade_frontalface_alt.xml");
        for (auto n : { "1.png","2.png","3.png" }) {
            vector<Rect> faces{};
            Mat m = imread(n, CV_LOAD_IMAGE_GRAYSCALE);
            facer.detectMultiScale(m, faces, 1.1, 3, CASCADE_SCALE_IMAGE, Size(50, 50));
            cnt += faces.size(); //vector given to detectMultiScale cleared in detectMultiScale
            cout << faces[0] << endl;
        }
        for (auto n : { "1.png","2.png","3.png" }) {
            vector<Rect> faces{};
            Mat m = imread(n, CV_LOAD_IMAGE_GRAYSCALE);
            facer.detectMultiScale(m, faces, 1.1, 3, CASCADE_SCALE_IMAGE, Size(50, 50));
            cnt += faces.size(); //vector given to detectMultiScale cleared in detectMultiScale
            cout << faces[0] << endl;
        }
        return cnt;
    }
    int reuse_call_reverse() {
        int cnt = 0;
        CascadeClassifier facer("haarcascade_frontalface_alt.xml");
        for (auto n : {"3.png" ,"2.png", "1.png"}) {
            vector<Rect> faces{};
            Mat m = imread(n, CV_LOAD_IMAGE_GRAYSCALE);
            facer.detectMultiScale(m, faces, 1.1, 3, CASCADE_SCALE_IMAGE, Size(50, 50));
            cnt += faces.size(); //vector given to detectMultiScale cleared in detectMultiScale
            cout << faces[0] << endl;
        }
        for (auto n : { "3.png" ,"2.png", "1.png" }) {
            vector<Rect> faces{};
            Mat m = imread(n, CV_LOAD_IMAGE_GRAYSCALE);
            facer.detectMultiScale(m, faces, 1.1, 3, CASCADE_SCALE_IMAGE, Size(50, 50));
            cnt += faces.size(); //vector given to detectMultiScale cleared in detectMultiScale
            cout << faces[0] << endl;
        }
        return cnt;
    }
    int main() {
        cout << "Created every image 2*3 files" << endl;
        cout << no_reuse_call() << endl;
        cout << "Created one time and files in alphabet order 2*3 files" <<  endl;
        cout << reuse_call() << endl;
        cout << "Created one time and files in contra - alphabet order 2*3 files" << endl;
        cout << reuse_call_reverse() << endl;
        cout << "You can see:" << endl;
        cout << "   if cascade is reused - detection in 3.png file is stabily wrong if it is processed after 1.png and 2.png" << endl;
        cout << "   it's depend on order - if 3.png is first in row it detected right even in second call after 1.png and 2.png" << endl;
        cout << "   it's random and based somehow on image - 1.png and 2.png are always detected validly" << endl;
        return 0;
    }

查看https://github.com/Itseez/opencv/issues/5475

由于某些原因,opencv3.0.0中的ocl不稳定因此作者建议调用setUseOpenCL(false(;在程序中-有了这个选项,所有都能很好地工作