simple_object_detector_py.h 11 KB
Newer Older
1
2
3
4
5
// Copyright (C) 2014  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.
#ifndef DLIB_SIMPLE_OBJECT_DETECTOR_PY_H__
#define DLIB_SIMPLE_OBJECT_DETECTOR_PY_H__

Davis King's avatar
Davis King committed
6
#include "opaque_types.h"
7
8
9
10
11
#include <dlib/python.h>
#include <dlib/matrix.h>
#include <dlib/geometry.h>
#include <dlib/image_processing/frontal_face_detector.h>

12
13
namespace py = pybind11;

14
15
16
17
namespace dlib
{
    typedef object_detector<scan_fhog_pyramid<pyramid_down<6> > > simple_object_detector;

18
19
20
21
    inline void split_rect_detections (
        std::vector<rect_detection>& rect_detections,
        std::vector<rectangle>& rectangles,
        std::vector<double>& detection_confidences,
22
        std::vector<unsigned long>& weight_indices
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    )
    {
        rectangles.clear();
        detection_confidences.clear();
        weight_indices.clear();

        for (unsigned long i = 0; i < rect_detections.size(); ++i)
        {
            rectangles.push_back(rect_detections[i].rect);
            detection_confidences.push_back(rect_detections[i].detection_confidence);
            weight_indices.push_back(rect_detections[i].weight_index);
        }
    }

Jack Culpepper's avatar
Jack Culpepper committed
37
38

    inline std::vector<dlib::rectangle> run_detector_with_upscale1 (
39
        dlib::simple_object_detector& detector,
40
        py::array img,
41
        const unsigned int upsampling_amount,
42
        const double adjust_threshold,
43
        std::vector<double>& detection_confidences,
44
        std::vector<unsigned long>& weight_indices
45
46
47
48
    )
    {
        pyramid_down<2> pyr;

49
50
51
        std::vector<rectangle> rectangles;
        std::vector<rect_detection> rect_detections;

52
        if (is_image<unsigned char>(img))
53
54
        {
            array2d<unsigned char> temp;
55
56
57
58
59
            auto img_view = make_image_view(numpy_image<unsigned char>(img));

            // Release the GIL so that this code can be run in parallel.
            py::gil_scoped_release release;

60
61
            if (upsampling_amount == 0)
            {
62
                detector(img_view, rect_detections, adjust_threshold);
63
64
65
                split_rect_detections(rect_detections, rectangles,
                                      detection_confidences, weight_indices);
                return rectangles;
66
67
68
            }
            else
            {
69
                pyramid_up(img_view, temp, pyr);
70
71
72
73
74
75
76
                unsigned int levels = upsampling_amount-1;
                while (levels > 0)
                {
                    levels--;
                    pyramid_up(temp);
                }

77
                detector(temp, rect_detections, adjust_threshold);
78
79
80
81
82
83
84
                for (unsigned long i = 0; i < rect_detections.size(); ++i)
                    rect_detections[i].rect = pyr.rect_down(rect_detections[i].rect,
                                                            upsampling_amount);
                split_rect_detections(rect_detections, rectangles,
                                      detection_confidences, weight_indices);

                return rectangles;
85
86
            }
        }
87
        else if (is_image<rgb_pixel>(img))
88
89
        {
            array2d<rgb_pixel> temp;
90
91
92
93
94
            auto img_view = make_image_view(numpy_image<rgb_pixel>(img));

            // Release the GIL so that this code can be run in parallel.
            py::gil_scoped_release release;

95
96
            if (upsampling_amount == 0)
            {
97
                detector(img_view, rect_detections, adjust_threshold);
98
99
100
                split_rect_detections(rect_detections, rectangles,
                                      detection_confidences, weight_indices);
                return rectangles;
101
102
103
            }
            else
            {
104
                pyramid_up(img_view, temp, pyr);
105
106
107
108
109
110
111
                unsigned int levels = upsampling_amount-1;
                while (levels > 0)
                {
                    levels--;
                    pyramid_up(temp);
                }

112
                detector(temp, rect_detections, adjust_threshold);
113
114
115
116
117
118
119
                for (unsigned long i = 0; i < rect_detections.size(); ++i)
                    rect_detections[i].rect = pyr.rect_down(rect_detections[i].rect,
                                                            upsampling_amount);
                split_rect_detections(rect_detections, rectangles,
                                      detection_confidences, weight_indices);

                return rectangles;
120
121
122
123
124
125
126
127
            }
        }
        else
        {
            throw dlib::error("Unsupported image type, must be 8bit gray or RGB image.");
        }
    }

128
129
    inline std::vector<dlib::rectangle> run_detectors_with_upscale1 (
        std::vector<simple_object_detector >& detectors,
130
        py::array img,
131
132
133
        const unsigned int upsampling_amount,
        const double adjust_threshold,
        std::vector<double>& detection_confidences,
134
        std::vector<unsigned long>& weight_indices
135
136
137
138
139
140
141
    )
    {
        pyramid_down<2> pyr;

        std::vector<rectangle> rectangles;
        std::vector<rect_detection> rect_detections;

142
        if (is_image<unsigned char>(img))
143
144
145
146
        {
            array2d<unsigned char> temp;
            if (upsampling_amount == 0)
            {
147
                evaluate_detectors(detectors, numpy_image<unsigned char>(img), rect_detections, adjust_threshold);
148
149
150
151
152
153
                split_rect_detections(rect_detections, rectangles,
                                      detection_confidences, weight_indices);
                return rectangles;
            }
            else
            {
154
                pyramid_up(numpy_image<unsigned char>(img), temp, pyr);
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
                unsigned int levels = upsampling_amount-1;
                while (levels > 0)
                {
                    levels--;
                    pyramid_up(temp);
                }

                evaluate_detectors(detectors, temp, rect_detections, adjust_threshold);
                for (unsigned long i = 0; i < rect_detections.size(); ++i)
                    rect_detections[i].rect = pyr.rect_down(rect_detections[i].rect,
                                                            upsampling_amount);
                split_rect_detections(rect_detections, rectangles,
                                      detection_confidences, weight_indices);

                return rectangles;
            }
        }
172
        else if (is_image<rgb_pixel>(img))
173
174
175
176
        {
            array2d<rgb_pixel> temp;
            if (upsampling_amount == 0)
            {
177
                evaluate_detectors(detectors, numpy_image<rgb_pixel>(img), rect_detections, adjust_threshold);
178
179
180
181
182
183
                split_rect_detections(rect_detections, rectangles,
                                      detection_confidences, weight_indices);
                return rectangles;
            }
            else
            {
184
                pyramid_up(numpy_image<rgb_pixel>(img), temp, pyr);
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
                unsigned int levels = upsampling_amount-1;
                while (levels > 0)
                {
                    levels--;
                    pyramid_up(temp);
                }

                evaluate_detectors(detectors, temp, rect_detections, adjust_threshold);
                for (unsigned long i = 0; i < rect_detections.size(); ++i)
                    rect_detections[i].rect = pyr.rect_down(rect_detections[i].rect,
                                                            upsampling_amount);
                split_rect_detections(rect_detections, rectangles,
                                      detection_confidences, weight_indices);

                return rectangles;
            }
        }
        else
        {
            throw dlib::error("Unsupported image type, must be 8bit gray or RGB image.");
        }
    }

Jack Culpepper's avatar
Jack Culpepper committed
208
209
    inline std::vector<dlib::rectangle> run_detector_with_upscale2 (
        dlib::simple_object_detector& detector,
210
        py::array img,
Jack Culpepper's avatar
Jack Culpepper committed
211
        const unsigned int upsampling_amount
212

Jack Culpepper's avatar
Jack Culpepper committed
213
214
215
    )
    {
        std::vector<double> detection_confidences;
216
        std::vector<unsigned long> weight_indices;
217
        const double adjust_threshold = 0.0;
Jack Culpepper's avatar
Jack Culpepper committed
218
219

        return run_detector_with_upscale1(detector, img, upsampling_amount,
220
                                          adjust_threshold,
Jack Culpepper's avatar
Jack Culpepper committed
221
222
223
                                          detection_confidences, weight_indices);
    }

224
    inline py::tuple run_rect_detector (
Jack Culpepper's avatar
Jack Culpepper committed
225
        dlib::simple_object_detector& detector,
226
        py::array img,
227
228
        const unsigned int upsampling_amount,
        const double adjust_threshold)
229
    {
230
        py::tuple t;
231
232

        std::vector<double> detection_confidences;
233
        std::vector<unsigned long> weight_indices;
234
235
        std::vector<rectangle> rectangles;

Jack Culpepper's avatar
Jack Culpepper committed
236
        rectangles = run_detector_with_upscale1(detector, img, upsampling_amount,
237
                                                adjust_threshold,
Jack Culpepper's avatar
Jack Culpepper committed
238
                                                detection_confidences, weight_indices);
239

240
        return py::make_tuple(rectangles,
241
242
                              vector_to_python_list(detection_confidences), 
                              vector_to_python_list(weight_indices));
243
244
    }

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
    struct simple_object_detector_py
    {
        simple_object_detector detector;
        unsigned int upsampling_amount;

        simple_object_detector_py() {}
        simple_object_detector_py(simple_object_detector& _detector, unsigned int _upsampling_amount) :
            detector(_detector), upsampling_amount(_upsampling_amount) {}

        std::vector<dlib::rectangle> run_detector1 (py::array img,
                                                    const unsigned int upsampling_amount_)
        {
            return run_detector_with_upscale2(detector, img, upsampling_amount_);
        }

        std::vector<dlib::rectangle> run_detector2 (py::array img)
        {
            return run_detector_with_upscale2(detector, img, upsampling_amount);
        }


    };

268
269
    inline py::tuple run_multiple_rect_detectors (
        py::list& detectors,
270
        py::array img,
271
272
273
        const unsigned int upsampling_amount,
        const double adjust_threshold)
    {
274
        py::tuple t;
275

276
        std::vector<simple_object_detector> vector_detectors;
277
278
279
280
        const unsigned long num_detectors = len(detectors);
        // Now copy the data into dlib based objects.
        for (unsigned long i = 0; i < num_detectors; ++i)
        {
281
282
283
284
285
286
287
            try
            {
                vector_detectors.push_back(detectors[i].cast<simple_object_detector>());
            } catch(py::cast_error&)
            {
                vector_detectors.push_back(detectors[i].cast<simple_object_detector_py>().detector);
            }
288
        }
289

290
        std::vector<double> detection_confidences;
291
        std::vector<unsigned long> weight_indices;
292
293
294
295
296
297
        std::vector<rectangle> rectangles;

        rectangles = run_detectors_with_upscale1(vector_detectors, img, upsampling_amount,
                                                adjust_threshold,
                                                detection_confidences, weight_indices);

298
        return py::make_tuple(rectangles,
299
300
                              vector_to_python_list(detection_confidences),
                              vector_to_python_list(weight_indices));
301
302
303
304
    }



305
306
307
}

#endif // DLIB_SIMPLE_OBJECT_DETECTOR_PY_H__