~paparazzi-uav/paparazzi/v5.0-manual

« back to all changes in this revision

Viewing changes to sw/ext/opencv_bebop/opencv/samples/tapi/ufacedetect.cpp

  • Committer: Paparazzi buildbot
  • Date: 2016-05-18 15:00:29 UTC
  • Revision ID: felix.ruess+docbot@gmail.com-20160518150029-e8lgzi5kvb4p7un9
Manual import commit 4b8bbb730080dac23cf816b98908dacfabe2a8ec from v5.0 branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "opencv2/objdetect.hpp"
 
2
#include "opencv2/highgui.hpp"
 
3
#include "opencv2/imgproc.hpp"
 
4
#include "opencv2/core/ocl.hpp"
 
5
#include <iostream>
 
6
 
 
7
using namespace std;
 
8
using namespace cv;
 
9
 
 
10
static void help()
 
11
{
 
12
    cout << "\nThis program demonstrates the cascade recognizer. Now you can use Haar or LBP features.\n"
 
13
            "This classifier can recognize many kinds of rigid objects, once the appropriate classifier is trained.\n"
 
14
            "It's most known use is for faces.\n"
 
15
            "Usage:\n"
 
16
            "./ufacedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face]\n"
 
17
               "   [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]\n"
 
18
               "   [--scale=<image scale greater or equal to 1, try 1.3 for example>]\n"
 
19
               "   [--try-flip]\n"
 
20
               "   [filename|camera_index]\n\n"
 
21
            "see facedetect.cmd for one call:\n"
 
22
            "./ufacedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml\" --scale=1.3\n\n"
 
23
            "During execution:\n\tHit any key to quit.\n"
 
24
            "\tUsing OpenCV version " << CV_VERSION << "\n" << endl;
 
25
}
 
26
 
 
27
void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade,
 
28
                    CascadeClassifier& nestedCascade,
 
29
                    double scale, bool tryflip );
 
30
 
 
31
string cascadeName = "../../data/haarcascades/haarcascade_frontalface_alt.xml";
 
32
string nestedCascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
 
33
 
 
34
int main( int argc, const char** argv )
 
35
{
 
36
    VideoCapture capture;
 
37
    UMat frame, image;
 
38
    Mat canvas;
 
39
 
 
40
    string inputName;
 
41
    bool tryflip;
 
42
 
 
43
    CascadeClassifier cascade, nestedCascade;
 
44
    double scale;
 
45
 
 
46
    cv::CommandLineParser parser(argc, argv,
 
47
        "{cascade|../../data/haarcascades/haarcascade_frontalface_alt.xml|}"
 
48
        "{nested-cascade|../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml|}"
 
49
        "{help h ||}{scale|1|}{try-flip||}{@filename||}"
 
50
    );
 
51
    if (parser.has("help"))
 
52
    {
 
53
        help();
 
54
        return 0;
 
55
    }
 
56
    cascadeName = parser.get<string>("cascade");
 
57
    nestedCascadeName = parser.get<string>("nested-cascade");
 
58
    scale = parser.get<double>("scale");
 
59
    tryflip = parser.has("try-flip");
 
60
    inputName = parser.get<string>("@filename");
 
61
    if ( !parser.check())
 
62
    {
 
63
        parser.printErrors();
 
64
        help();
 
65
        return -1;
 
66
    }
 
67
 
 
68
    if ( !nestedCascade.load( nestedCascadeName ) )
 
69
        cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;
 
70
    if( !cascade.load( cascadeName ) )
 
71
    {
 
72
        cerr << "ERROR: Could not load classifier cascade" << endl;
 
73
        help();
 
74
        return -1;
 
75
    }
 
76
 
 
77
    cout << "old cascade: " << (cascade.isOldFormatCascade() ? "TRUE" : "FALSE") << endl;
 
78
 
 
79
    if( inputName.empty() || (isdigit(inputName[0]) && inputName.size() == 1) )
 
80
    {
 
81
        int c = inputName.empty() ? 0 : inputName[0] - '0';
 
82
        if(!capture.open(c))
 
83
            cout << "Capture from camera #" <<  c << " didn't work" << endl;
 
84
    }
 
85
    else
 
86
    {
 
87
        if( inputName.empty() )
 
88
            inputName = "../data/lena.jpg";
 
89
        image = imread( inputName, 1 ).getUMat(ACCESS_READ);
 
90
        if( image.empty() )
 
91
        {
 
92
            if(!capture.open( inputName ))
 
93
                cout << "Could not read " << inputName << endl;
 
94
        }
 
95
    }
 
96
 
 
97
    if( capture.isOpened() )
 
98
    {
 
99
        cout << "Video capturing has been started ..." << endl;
 
100
        for(;;)
 
101
        {
 
102
            capture >> frame;
 
103
            if( frame.empty() )
 
104
                break;
 
105
 
 
106
            detectAndDraw( frame, canvas, cascade, nestedCascade, scale, tryflip );
 
107
 
 
108
            int c = waitKey(10);
 
109
            if( c == 27 || c == 'q' || c == 'Q' )
 
110
                break;
 
111
        }
 
112
    }
 
113
    else
 
114
    {
 
115
        cout << "Detecting face(s) in " << inputName << endl;
 
116
        if( !image.empty() )
 
117
        {
 
118
            detectAndDraw( image, canvas, cascade, nestedCascade, scale, tryflip );
 
119
            waitKey(0);
 
120
        }
 
121
        else if( !inputName.empty() )
 
122
        {
 
123
            /* assume it is a text file containing the
 
124
            list of the image filenames to be processed - one per line */
 
125
            FILE* f = fopen( inputName.c_str(), "rt" );
 
126
            if( f )
 
127
            {
 
128
                char buf[1000+1];
 
129
                while( fgets( buf, 1000, f ) )
 
130
                {
 
131
                    int len = (int)strlen(buf), c;
 
132
                    while( len > 0 && isspace(buf[len-1]) )
 
133
                        len--;
 
134
                    buf[len] = '\0';
 
135
                    cout << "file " << buf << endl;
 
136
                    image = imread( buf, 1 ).getUMat(ACCESS_READ);
 
137
                    if( !image.empty() )
 
138
                    {
 
139
                        detectAndDraw( image, canvas, cascade, nestedCascade, scale, tryflip );
 
140
                        c = waitKey(0);
 
141
                        if( c == 27 || c == 'q' || c == 'Q' )
 
142
                            break;
 
143
                    }
 
144
                    else
 
145
                    {
 
146
                        cerr << "Aw snap, couldn't read image " << buf << endl;
 
147
                    }
 
148
                }
 
149
                fclose(f);
 
150
            }
 
151
        }
 
152
    }
 
153
 
 
154
    return 0;
 
155
}
 
156
 
 
157
void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade,
 
158
                    CascadeClassifier& nestedCascade,
 
159
                    double scale, bool tryflip )
 
160
{
 
161
    double t = 0;
 
162
    vector<Rect> faces, faces2;
 
163
    const static Scalar colors[] =
 
164
    {
 
165
        Scalar(255,0,0),
 
166
        Scalar(255,128,0),
 
167
        Scalar(255,255,0),
 
168
        Scalar(0,255,0),
 
169
        Scalar(0,128,255),
 
170
        Scalar(0,255,255),
 
171
        Scalar(0,0,255),
 
172
        Scalar(255,0,255)
 
173
    };
 
174
    static UMat gray, smallImg;
 
175
 
 
176
    t = (double)getTickCount();
 
177
 
 
178
    cvtColor( img, gray, COLOR_BGR2GRAY );
 
179
    double fx = 1 / scale;
 
180
    resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR );
 
181
    equalizeHist( smallImg, smallImg );
 
182
 
 
183
    cascade.detectMultiScale( smallImg, faces,
 
184
        1.1, 3, 0
 
185
        //|CASCADE_FIND_BIGGEST_OBJECT
 
186
        //|CASCADE_DO_ROUGH_SEARCH
 
187
        |CASCADE_SCALE_IMAGE,
 
188
        Size(30, 30) );
 
189
    if( tryflip )
 
190
    {
 
191
        flip(smallImg, smallImg, 1);
 
192
        cascade.detectMultiScale( smallImg, faces2,
 
193
                                 1.1, 2, 0
 
194
                                 //|CASCADE_FIND_BIGGEST_OBJECT
 
195
                                 //|CASCADE_DO_ROUGH_SEARCH
 
196
                                 |CASCADE_SCALE_IMAGE,
 
197
                                 Size(30, 30) );
 
198
        for( vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); r++ )
 
199
        {
 
200
            faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height));
 
201
        }
 
202
    }
 
203
    t = (double)getTickCount() - t;
 
204
    img.copyTo(canvas);
 
205
 
 
206
    double fps = getTickFrequency()/t;
 
207
    static double avgfps = 0;
 
208
    static int nframes = 0;
 
209
    nframes++;
 
210
    double alpha = nframes > 50 ? 0.01 : 1./nframes;
 
211
    avgfps = avgfps*(1-alpha) + fps*alpha;
 
212
 
 
213
    putText(canvas, format("OpenCL: %s, fps: %.1f", ocl::useOpenCL() ? "ON" : "OFF", avgfps), Point(50, 30),
 
214
            FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0,255,0), 2);
 
215
 
 
216
    for ( size_t i = 0; i < faces.size(); i++ )
 
217
    {
 
218
        Rect r = faces[i];
 
219
        vector<Rect> nestedObjects;
 
220
        Point center;
 
221
        Scalar color = colors[i%8];
 
222
        int radius;
 
223
 
 
224
        double aspect_ratio = (double)r.width/r.height;
 
225
        if( 0.75 < aspect_ratio && aspect_ratio < 1.3 )
 
226
        {
 
227
            center.x = cvRound((r.x + r.width*0.5)*scale);
 
228
            center.y = cvRound((r.y + r.height*0.5)*scale);
 
229
            radius = cvRound((r.width + r.height)*0.25*scale);
 
230
            circle( canvas, center, radius, color, 3, 8, 0 );
 
231
        }
 
232
        else
 
233
            rectangle( canvas, Point(cvRound(r.x*scale), cvRound(r.y*scale)),
 
234
                       Point(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)),
 
235
                       color, 3, 8, 0);
 
236
        if( nestedCascade.empty() )
 
237
            continue;
 
238
        UMat smallImgROI = smallImg(r);
 
239
        nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
 
240
            1.1, 2, 0
 
241
            //|CASCADE_FIND_BIGGEST_OBJECT
 
242
            //|CASCADE_DO_ROUGH_SEARCH
 
243
            //|CASCADE_DO_CANNY_PRUNING
 
244
            |CASCADE_SCALE_IMAGE,
 
245
            Size(30, 30) );
 
246
 
 
247
        for ( size_t j = 0; j < nestedObjects.size(); j++ )
 
248
        {
 
249
            Rect nr = nestedObjects[j];
 
250
            center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale);
 
251
            center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale);
 
252
            radius = cvRound((nr.width + nr.height)*0.25*scale);
 
253
            circle( canvas, center, radius, color, 3, 8, 0 );
 
254
        }
 
255
    }
 
256
    imshow( "result", canvas );
 
257
}