load_image_dataset.h 12.4 KB
Newer Older
1
2
// Copyright (C) 2012  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.
3
4
#ifndef DLIB_LOAD_IMAGE_DaTASET_Hh_
#define DLIB_LOAD_IMAGE_DaTASET_Hh_
5
6
7
8
9
10
11
12
13
14

#include "load_image_dataset_abstract.h"
#include "../misc_api.h"
#include "../dir_nav.h"
#include "../image_io.h"
#include "../array.h"
#include <vector>
#include "../geometry.h"
#include "image_dataset_metadata.h"
#include <string>
15
#include <set>
16
#include "../image_processing/full_object_detection.h"
17
#include <utility>
18
19
20
21
22


namespace dlib
{

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// ----------------------------------------------------------------------------------------

    class image_dataset_file
    {
    public:
        image_dataset_file(const std::string& filename)
        {
            _skip_empty_images = false;
            _have_parts = false;
            _filename = filename;
        }

        image_dataset_file boxes_match_label(
            const std::string& label
        ) const
        {
            image_dataset_file temp(*this);
            temp._labels.insert(label);
            return temp;
        }

        image_dataset_file skip_empty_images(
        ) const
        {
            image_dataset_file temp(*this);
            temp._skip_empty_images = true;
            return temp;
        }

        image_dataset_file boxes_have_parts(
        ) const
        {
            image_dataset_file temp(*this);
            temp._have_parts = true;
            return temp;
        }

        bool should_load_box (
            const image_dataset_metadata::box& box
        ) const
        {
            if (_have_parts && box.parts.size() == 0)
                return false;
            if (_labels.size() == 0)
                return true;
            if (_labels.count(box.label) != 0)
                return true;
            return false;
        }

        const std::string& get_filename() const { return _filename; }
        bool should_skip_empty_images() const { return _skip_empty_images; }
        bool should_boxes_have_parts() const { return _have_parts; }
        const std::set<std::string>& get_selected_box_labels() const { return _labels; }

    private:
        std::string _filename;
        std::set<std::string> _labels;
        bool _skip_empty_images;
        bool _have_parts;
    };

85
86
87
// ----------------------------------------------------------------------------------------

    template <
88
        typename array_type
89
        >
90
    std::vector<std::vector<rectangle> > load_image_dataset (
91
        array_type& images,
92
        std::vector<std::vector<rectangle> >& object_locations,
93
        const image_dataset_file& source
94
95
96
97
98
99
    )
    {
        images.clear();
        object_locations.clear();
        const std::string old_working_dir = get_current_dir();

100
101
        std::vector<std::vector<rectangle> > ignored_rects;

102
103
        using namespace dlib::image_dataset_metadata;
        dataset data;
104
        load_image_dataset_metadata(data, source.get_filename());
105

106
107
108
        // Set the current directory to be the one that contains the
        // metadata file. We do this because the file might contain
        // file paths which are relative to this folder.
109
        set_current_dir(get_parent_directory(file(source.get_filename())));
110
111


112
        typedef typename array_type::value_type image_type;
113
114


115
        image_type img;
116
        std::vector<rectangle> rects, ignored;
117
118
119
        for (unsigned long i = 0; i < data.images.size(); ++i)
        {
            rects.clear();
120
            ignored.clear();
121
122
            for (unsigned long j = 0; j < data.images[i].boxes.size(); ++j)
            {
123
                if (source.should_load_box(data.images[i].boxes[j]))
124
                {
125
126
127
128
                    if (data.images[i].boxes[j].ignore)
                        ignored.push_back(data.images[i].boxes[j].rect);
                    else
                        rects.push_back(data.images[i].boxes[j].rect);
129
130
                }
            }
131

132
            if (!source.should_skip_empty_images() || rects.size() != 0)
133
134
            {
                object_locations.push_back(rects);
135
                ignored_rects.push_back(ignored);
136
137
138
                load_image(img, data.images[i].filename);
                images.push_back(img);
            }
139
140
141
        }

        set_current_dir(old_working_dir);
142
        return ignored_rects;
143
144
    }

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// ----------------------------------------------------------------------------------------

    template <
        typename array_type
        >
    void load_image_dataset (
        array_type& images,
        std::vector<std::vector<mmod_rect> >& object_locations,
        const image_dataset_file& source
    )
    {
        images.clear();
        object_locations.clear();

        using namespace dlib::image_dataset_metadata;
        dataset data;
        load_image_dataset_metadata(data, source.get_filename());

        // Set the current directory to be the one that contains the
        // metadata file. We do this because the file might contain
        // file paths which are relative to this folder.
        locally_change_current_dir chdir(get_parent_directory(file(source.get_filename())));

        typedef typename array_type::value_type image_type;

        image_type img;
        std::vector<mmod_rect> rects;
        for (unsigned long i = 0; i < data.images.size(); ++i)
        {
            rects.clear();
            for (unsigned long j = 0; j < data.images[i].boxes.size(); ++j)
            {
                if (source.should_load_box(data.images[i].boxes[j]))
                {
                    if (data.images[i].boxes[j].ignore)
                        rects.push_back(ignored_mmod_rect(data.images[i].boxes[j].rect));
                    else
                        rects.push_back(mmod_rect(data.images[i].boxes[j].rect));
                }
            }

            if (!source.should_skip_empty_images() || rects.size() != 0)
            {
                object_locations.push_back(std::move(rects));
                load_image(img, data.images[i].filename);
                images.push_back(std::move(img));
            }
        }
    }

195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
// ----------------------------------------------------------------------------------------

// ******* THIS FUNCTION IS DEPRECATED, you should use another version of load_image_dataset() *******
    template <
        typename image_type, 
        typename MM
        >
    std::vector<std::vector<rectangle> > load_image_dataset (
        array<image_type,MM>& images,
        std::vector<std::vector<rectangle> >& object_locations,
        const std::string& filename,
        const std::string& label,
        bool skip_empty_images = false
    )
    {
        image_dataset_file f(filename);
        if (label.size() != 0)
            f = f.boxes_match_label(label);
        if (skip_empty_images)
            f = f.skip_empty_images();
        return load_image_dataset(images, object_locations, f);
    }

218
219
// ----------------------------------------------------------------------------------------

Davis King's avatar
Davis King committed
220
    template <
221
        typename array_type
Davis King's avatar
Davis King committed
222
        >
223
    std::vector<std::vector<rectangle> > load_image_dataset (
224
        array_type& images,
225
226
227
228
        std::vector<std::vector<rectangle> >& object_locations,
        const std::string& filename
    )
    {
229
        return load_image_dataset(images, object_locations, image_dataset_file(filename));
230
231
    }

232
233
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
234
// ----------------------------------------------------------------------------------------
235
236

    template <
237
        typename array_type
238
        >
239
    std::vector<std::vector<rectangle> > load_image_dataset (
240
        array_type& images,
241
        std::vector<std::vector<full_object_detection> >& object_locations,
242
243
        const image_dataset_file& source,
        std::vector<std::string>& parts_list
244
245
    )
    {
246
        typedef typename array_type::value_type image_type;
247
        parts_list.clear();
248
249
250
251
        images.clear();
        object_locations.clear();
        const std::string old_working_dir = get_current_dir();

252
253
        using namespace dlib::image_dataset_metadata;
        dataset data;
254
        load_image_dataset_metadata(data, source.get_filename());
255

256
257
258
        // Set the current directory to be the one that contains the
        // metadata file. We do this because the file might contain
        // file paths which are relative to this folder.
259
        set_current_dir(get_parent_directory(file(source.get_filename())));
260
261
262
263
264
265
266
267
268


        std::set<std::string> all_parts;

        // find out what parts are being used in the dataset.  Store results in all_parts.
        for (unsigned long i = 0; i < data.images.size(); ++i)
        {
            for (unsigned long j = 0; j < data.images[i].boxes.size(); ++j)
            {
269
                if (source.should_load_box(data.images[i].boxes[j]))
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
                {
                    const std::map<std::string,point>& parts = data.images[i].boxes[j].parts;
                    std::map<std::string,point>::const_iterator itr;

                    for (itr = parts.begin(); itr != parts.end(); ++itr)
                    {
                        all_parts.insert(itr->first);
                    }
                }
            }
        }

        // make a mapping between part names and the integers [0, all_parts.size())
        std::map<std::string,int> parts_idx;
        for (std::set<std::string>::iterator i = all_parts.begin(); i != all_parts.end(); ++i)
        {
286
287
            parts_idx[*i] = parts_list.size();
            parts_list.push_back(*i);
288
289
        }

290
291
        std::vector<std::vector<rectangle> > ignored_rects;
        std::vector<rectangle> ignored;
292
        image_type img;
293
294
295
296
        std::vector<full_object_detection> object_dets;
        for (unsigned long i = 0; i < data.images.size(); ++i)
        {
            object_dets.clear();
297
            ignored.clear();
298
299
            for (unsigned long j = 0; j < data.images[i].boxes.size(); ++j)
            {
300
                if (source.should_load_box(data.images[i].boxes[j]))
301
                {
302
                    if (data.images[i].boxes[j].ignore)
303
                    {
304
                        ignored.push_back(data.images[i].boxes[j].rect);
305
                    }
306
307
308
                    else
                    {
                        std::vector<point> partlist(parts_idx.size(), OBJECT_PART_NOT_PRESENT);
309

310
311
312
313
314
315
316
317
318
319
                        // populate partlist with all the parts present in this box.
                        const std::map<std::string,point>& parts = data.images[i].boxes[j].parts;
                        std::map<std::string,point>::const_iterator itr;
                        for (itr = parts.begin(); itr != parts.end(); ++itr)
                        {
                            partlist[parts_idx[itr->first]] = itr->second;
                        }

                        object_dets.push_back(full_object_detection(data.images[i].boxes[j].rect, partlist));
                    }
320
321
                }
            }
322

323
            if (!source.should_skip_empty_images() || object_dets.size() != 0)
324
325
            {
                object_locations.push_back(object_dets);
326
                ignored_rects.push_back(ignored);
327
328
329
                load_image(img, data.images[i].filename);
                images.push_back(img);
            }
330
331
332
333
        }

        set_current_dir(old_working_dir);

334
335
336
337
338
339
        return ignored_rects;
    }

// ----------------------------------------------------------------------------------------

    template <
340
        typename array_type
341
342
        >
    std::vector<std::vector<rectangle> > load_image_dataset (
343
        array_type& images,
344
345
346
347
348
349
        std::vector<std::vector<full_object_detection> >& object_locations,
        const image_dataset_file& source 
    )
    {
        std::vector<std::string> parts_list;
        return load_image_dataset(images, object_locations, source, parts_list);
350
351
352
353
354
    }

// ----------------------------------------------------------------------------------------

    template <
355
        typename array_type 
356
        >
357
    std::vector<std::vector<rectangle> > load_image_dataset (
358
        array_type& images,
359
360
361
362
        std::vector<std::vector<full_object_detection> >& object_locations,
        const std::string& filename
    )
    {
363
364
        std::vector<std::string> parts_list;
        return load_image_dataset(images, object_locations, image_dataset_file(filename), parts_list);
365
366
367
368
    }

// ----------------------------------------------------------------------------------------

369
370
}

371
#endif // DLIB_LOAD_IMAGE_DaTASET_Hh_
372