使用facedetect.cpp在裁剪图像中检测眼睛

我使用OpenCV进行人脸和眼睛检测。首先,我测试了OpenCV/Samples/c/facedetect.cpp中的示例程序。我为facedetect.exe提供了两张图像作为输入——一张是完整的,另一张是同一个人的裁剪面部。现在,facedetect.cpp在处理完整图像时运行正常,而在输入裁剪图像时甚至无法检测到面部。

尽管裁剪图像仅包含使用OpenCV人脸检测器裁剪的面部,但在某些糟糕的情况下,我只能得到嘴巴或嘴唇,或者只是面部的一部分。因此,我的需求是检查图像中是否有两只眼睛。

下面是两张示例图片,其中一张是完整图像,我可以得到正确的输出:enter image description here

下面是需要使用facedetect.cpp检测眼睛的图像:

enter image description here

所以我的问题是如何在裁剪图像中检测眼睛?

下面是示例facedetect.cpp的代码

#include "opencv2/objdetect/objdetect.hpp"#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include <iostream>#include <stdio.h>using namespace std;using namespace cv;static void help(){    cout << "\nThis program demonstrates the cascade recognizer. Now you can use Haar or LBP features.\n"            "This classifier can recognize many ~rigid objects, it's most known use is for faces.\n"            "Usage:\n"            "./facedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face]\n"               "   [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]\n"               "   [--scale=<image scale greater or equal to 1, try 1.3 for example>\n"               "   [filename|camera_index]\n\n"            "see facedetect.cmd for one call:\n"            "./facedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye.xml\" --scale=1.3 \n"            "Hit any key to quit.\n"            "Using OpenCV version " << CV_VERSION << "\n" << endl;}void detectAndDraw( Mat& img,                   CascadeClassifier& cascade, CascadeClassifier& nestedCascade,                   double scale);String cascadeName = "../../data/haarcascades/haarcascade_frontalface_alt.xml";String nestedCascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";int main( int argc, const char** argv ){    CvCapture* capture = 0;    Mat frame, frameCopy, image;    const String scaleOpt = "--scale=";    size_t scaleOptLen = scaleOpt.length();    const String cascadeOpt = "--cascade=";    size_t cascadeOptLen = cascadeOpt.length();    const String nestedCascadeOpt = "--nested-cascade";    size_t nestedCascadeOptLen = nestedCascadeOpt.length();    String inputName;    help();    CascadeClassifier cascade, nestedCascade;    double scale = 1;    for( int i = 1; i < argc; i++ )    {        cout << "Processing " << i << " " <<  argv[i] << endl;        if( cascadeOpt.compare( 0, cascadeOptLen, argv[i], cascadeOptLen ) == 0 )        {            cascadeName.assign( argv[i] + cascadeOptLen );            cout << "  from which we have cascadeName= " << cascadeName << endl;        }        else if( nestedCascadeOpt.compare( 0, nestedCascadeOptLen, argv[i], nestedCascadeOptLen ) == 0 )        {            if( argv[i][nestedCascadeOpt.length()] == '=' )                nestedCascadeName.assign( argv[i] + nestedCascadeOpt.length() + 1 );            if( !nestedCascade.load( nestedCascadeName ) )                cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;        }        else if( scaleOpt.compare( 0, scaleOptLen, argv[i], scaleOptLen ) == 0 )        {            if( !sscanf( argv[i] + scaleOpt.length(), "%lf", &scale ) || scale < 1 )                scale = 1;            cout << " from which we read scale = " << scale << endl;        }        else if( argv[i][0] == '-' )        {            cerr << "WARNING: Unknown option %s" << argv[i] << endl;        }        else            inputName.assign( argv[i] );    }    if( !cascade.load( cascadeName ) )    {        cerr << "ERROR: Could not load classifier cascade" << endl;        cerr << "Usage: facedetect [--cascade=<cascade_path>]\n"            "   [--nested-cascade[=nested_cascade_path]]\n"            "   [--scale[=<image scale>\n"            "   [filename|camera_index]\n" << endl ;        return -1;    }    if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') )    {        capture = cvCaptureFromCAM( inputName.empty() ? 0 : inputName.c_str()[0] - '0' );        int c = inputName.empty() ? 0 : inputName.c_str()[0] - '0' ;        if(!capture) cout << "Capture from CAM " <<  c << " didn't work" << endl;    }    else if( inputName.size() )    {        image = imread( inputName, 1 );        if( image.empty() )        {            capture = cvCaptureFromAVI( inputName.c_str() );            if(!capture) cout << "Capture from AVI didn't work" << endl;        }    }    else    {        image = imread( "lena.jpg", 1 );        if(image.empty()) cout << "Couldn't read lena.jpg" << endl;    }    cvNamedWindow( "result", 1 );    if( capture )    {        cout << "In capture ..." << endl;        for(;;)        {            IplImage* iplImg = cvQueryFrame( capture );            frame = iplImg;            if( frame.empty() )                break;            if( iplImg->origin == IPL_ORIGIN_TL )                frame.copyTo( frameCopy );            else                flip( frame, frameCopy, 0 );            detectAndDraw( frameCopy, cascade, nestedCascade, scale );            if( waitKey( 10 ) >= 0 )                goto _cleanup_;        }        waitKey(0);_cleanup_:        cvReleaseCapture( &capture );    }    else    {        cout << "In image read" << endl;        if( !image.empty() )        {            detectAndDraw( image, cascade, nestedCascade, scale );            waitKey(0);        }        else if( !inputName.empty() )        {            /* assume it is a text file containing the            list of the image filenames to be processed - one per line */            FILE* f = fopen( inputName.c_str(), "rt" );            if( f )            {                char buf[1000+1];                while( fgets( buf, 1000, f ) )                {                    int len = (int)strlen(buf), c;                    while( len > 0 && isspace(buf[len-1]) )                        len--;                    buf[len] = '\0';                    cout << "file " << buf << endl;                    image = imread( buf, 1 );                    if( !image.empty() )                    {                        detectAndDraw( image, cascade, nestedCascade, scale );                        c = waitKey(0);                        if( c == 27 || c == 'q' || c == 'Q' )                            break;                    }                    else                    {                        cerr << "Aw snap, couldn't read image " << buf << endl;                    }                }                fclose(f);            }        }    }    cvDestroyWindow("result");    return 0;}

回答:

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注