• [转]让opencv输出人脸检测的得分(置信率)


    转自:http://www.cnblogs.com/sciencefans/

    作者:sciencefans

    最近项目略多,其中一个需要找出一些和脸比较像但是不是脸的负样本,想用opencv的人脸检测器检测到的错误脸作为这样的负样本。

    但是国内(包括国外)居然几乎没有相关的资料如何输出detectMultiScale()的置信率或者说是人脸得分

    所以写一篇小小的总结供有相关需求的人参考。

    转载需注明:http://www.cnblogs.com/sciencefans/

    看了下人脸识别函数的opencv的源码

    sourcesmodulesobjdetectsrccascadedetect.cpp

    中detectMultiScale有两个重载,第二个重载在opencv的开发文档里居然只字未提:

    void CascadeClassifier::detectMultiScale( const Mat& image, vector<Rect>& objects,
                                              vector<int>& rejectLevels,
                                              vector<double>& levelWeights,
                                              double scaleFactor, int minNeighbors,
                                              int flags, Size minObjectSize, Size maxObjectSize,
                                              bool outputRejectLevels )

    发现他有个rejectLevels和levelWeight这两个引用参数,看名字感觉是一种得分输出。

    google了一下发现国外问的人不少但是基本没啥解释(或者是我没认真找?)

    然后看了下它调用的cvHaarDetectObjectsForROC()的源码实现,大概懂了这俩vectors是在干什么的。

    先上结论:确实和人脸得分有关。

    首先应该明白一点detectMultiScale()这个方法是一个级联分类器,使用了boosting的方法。所以输入图像要经过层层(级级)选拔,留到最后的才是真汉子(正样本)

    rejectLevels就是代表在第几层被out的。如果是最后一层(在lbpcascade_frontalface.xml中是20,具体要看xml中的叙述)被out,则说明很可能是正样本。

    为啥说很可能呢?

    因为还有个参数:levelWeight。即使是在最后一层被out的,levelWeight很小甚至是负数,也可以看成是负样本。

    实际上很多负样本正是在最后一层被out的。

    见下图:

    我这里只截取了level在20才out的框。输出了他们的levelWeight。是脸的地方最大是4.23多,其他的就很小。不用过多解释了吧~

    所以这个函数的原理是这样的(个人理解,有错误请指教):

    首先一个level一个level地测试样本,然后每一个level给一个对应的得分,也就是levelWeight,如果这个weight低于或者高于对应level的threshold,则被抛弃。

    坚持到最后一个level并且在最后一个level仍然满足threshold的框就是正确的脸(正样本)。

    所以,人脸的分应该是这样:level越大,分数越高,在相同的level,levelWeight越大分数越高。

    但是实际上真正的人脸都是能坚持到level20(最后一个level)的,所以只比对最后一个level的所有大于1的框的levelWeight进行比对就可以知道脸的得分啦~

    这里给出所有level被gg的框的图:

    最后给出灰常短小精悍的demo的源代码:

    复制代码
     1 #include <opencv2opencv.hpp>
     2 #include <iostream>
     3 #include <vector>
     4 #include <fstream>
     5 #include <math.h>
     6 using namespace std;
     7 using namespace cv;
     8 const string xmlpath = "lbpcascade_frontalface.xml";
     9 CascadeClassifier face_cc;
    10 
    11 int tic = 0;
    12 
    13 void detect(Mat img){
    14     vector<Rect> faces;
    15     vector<int> rejLevel;
    16     vector<double> levelW;
    17     Mat grayimg;
    18     cvtColor(img, grayimg, CV_RGB2GRAY);
    19     equalizeHist(grayimg, grayimg);
    20     int minl = min(img.rows, img.cols);
    21     face_cc.detectMultiScale(grayimg, faces, rejLevel, levelW, 1.1, 3, 0, Size(), Size(), true);
    22     //face_cc.detectMultiScale(grayimg, faces, 1.1);
    23     for ( int i = 0; i < faces.size(); i++ )
    24     {
    25         if ( rejLevel[i] < 00 )
    26         {
    27             continue;
    28         }
    29         stringstream text1, text2;
    30         text1 << "rejLevel:" << rejLevel[ i ];
    31         text2 << "levelW:" << levelW[ i ];
    32         string ttt = text1.str();
    33         rectangle(img, faces[ i ], Scalar(255, 255, 0), 2, 8, 0);
    34         putText(img, ttt, cvPoint(faces[ i ].x, faces[ i ].y - 3), 1, 1, Scalar(0,255,255));
    35         ttt = text2.str();
    36         putText(img, ttt, cvPoint(faces[ i ].x, faces[ i ].y + 12), 1, 1, Scalar(255, 0, 255));
    37     }
    38     imshow("IMG", img);
    39     waitKey(0);
    40 }
    41 
    42 int main(){
    43     if ( !face_cc.load(xmlpath) )
    44     {
    45         cout << "load error!
    ";
    46         return -1;
    47     }
    48     ifstream pathin;
    49     pathin.open("imgpath.txt");
    50     string t;
    51     while ( pathin >> t && tic < 10000)
    52     {
    53         Mat img = imread(t);
    54         detect(img);
    55     }
    56     pathin.close();
    57     return 0;
    58 }
    复制代码
  • 相关阅读:
    使用Subversion进行版本控制 针对 Subversion 1.4(根据r2866编译)-------<转载>这是重要的知识点
    UIImageView上添加Button不能响应点击事件[转]
    Unity3D基础学习篇Unity基本原理
    ObjectiveC基础知识-查漏补缺
    C# 参考之方法参数关键字:params、ref及out
    SQL SERVER 2000 创建挂起的文件操作 解决方法
    JavaScript trim函数大赏
    javascript的date对象的方法
    firefox getRangeAt
    ckeditor+ckfinder
  • 原文地址:https://www.cnblogs.com/wing-xiong/p/5056422.html
Copyright © 2020-2023  润新知