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

#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
18
19
20
21


namespace dlib
{

22
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
// ----------------------------------------------------------------------------------------

    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;
    };

84
85
86
87
88
89
// ----------------------------------------------------------------------------------------

    template <
        typename image_type, 
        typename MM
        >
90
    std::vector<std::vector<rectangle> > load_image_dataset (
91
92
        array<image_type,MM>& images,
        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
113




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

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

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

144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// ----------------------------------------------------------------------------------------

// ******* 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);
    }

167
168
// ----------------------------------------------------------------------------------------

Davis King's avatar
Davis King committed
169
170
171
172
    template <
        typename image_type, 
        typename MM
        >
173
    std::vector<std::vector<rectangle> > load_image_dataset (
174
175
176
177
178
        array<image_type,MM>& images,
        std::vector<std::vector<rectangle> >& object_locations,
        const std::string& filename
    )
    {
179
        return load_image_dataset(images, object_locations, image_dataset_file(filename));
180
181
    }

182
183
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
184
// ----------------------------------------------------------------------------------------
185
186
187
188
189

    template <
        typename image_type, 
        typename MM
        >
190
    std::vector<std::vector<rectangle> > load_image_dataset (
191
192
        array<image_type,MM>& images,
        std::vector<std::vector<full_object_detection> >& object_locations,
193
194
        const image_dataset_file& source,
        std::vector<std::string>& parts_list
195
196
    )
    {
197
        parts_list.clear();
198
199
200
201
        images.clear();
        object_locations.clear();
        const std::string old_working_dir = get_current_dir();

202
203
        using namespace dlib::image_dataset_metadata;
        dataset data;
204
        load_image_dataset_metadata(data, source.get_filename());
205

206
207
208
        // 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.
209
        set_current_dir(get_parent_directory(file(source.get_filename())));
210
211
212
213
214
215
216
217
218


        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)
            {
219
                if (source.should_load_box(data.images[i].boxes[j]))
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
                {
                    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)
        {
236
237
            parts_idx[*i] = parts_list.size();
            parts_list.push_back(*i);
238
239
        }

240
241
        std::vector<std::vector<rectangle> > ignored_rects;
        std::vector<rectangle> ignored;
242
        image_type img;
243
244
245
246
        std::vector<full_object_detection> object_dets;
        for (unsigned long i = 0; i < data.images.size(); ++i)
        {
            object_dets.clear();
247
            ignored.clear();
248
249
            for (unsigned long j = 0; j < data.images[i].boxes.size(); ++j)
            {
250
                if (source.should_load_box(data.images[i].boxes[j]))
251
                {
252
                    if (data.images[i].boxes[j].ignore)
253
                    {
254
                        ignored.push_back(data.images[i].boxes[j].rect);
255
                    }
256
257
258
                    else
                    {
                        std::vector<point> partlist(parts_idx.size(), OBJECT_PART_NOT_PRESENT);
259

260
261
262
263
264
265
266
267
268
269
                        // 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));
                    }
270
271
                }
            }
272

273
            if (!source.should_skip_empty_images() || object_dets.size() != 0)
274
275
            {
                object_locations.push_back(object_dets);
276
                ignored_rects.push_back(ignored);
277
278
279
                load_image(img, data.images[i].filename);
                images.push_back(img);
            }
280
281
282
283
        }

        set_current_dir(old_working_dir);

284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
        return ignored_rects;
    }

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

    template <
        typename image_type, 
        typename MM
        >
    std::vector<std::vector<rectangle> > load_image_dataset (
        array<image_type,MM>& images,
        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);
301
302
303
304
305
306
307
308
    }

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

    template <
        typename image_type, 
        typename MM
        >
309
    std::vector<std::vector<rectangle> > load_image_dataset (
310
311
312
313
314
        array<image_type,MM>& images,
        std::vector<std::vector<full_object_detection> >& object_locations,
        const std::string& filename
    )
    {
315
316
        std::vector<std::string> parts_list;
        return load_image_dataset(images, object_locations, image_dataset_file(filename), parts_list);
317
318
319
320
    }

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

321
322
323
324
}

#endif // DLIB_LOAD_IMAGE_DaTASET_H__