main.cpp 6.73 KB
Newer Older
1

2
#include "image_dataset_metadata.h"
3
#include "metadata_editor.h"
4

5
6
#include <iostream>
#include <fstream>
7
#include <string>
8
#include <set>
9
10

#include <dlib/cmd_line_parser.h>
11
#include <dlib/dir_nav.h>
12
13


Davis King's avatar
Davis King committed
14
15
16
const char* VERSION = "0.1";


Davis King's avatar
Davis King committed
17
typedef dlib::cmd_line_parser<char>::check_1a_c parser_type;
18
19
20
21

using namespace std;
using 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
std::string strip_path (
    const std::string& str,
    const std::string& prefix
)
{
    unsigned long i;
    for (i = 0; i < str.size() && i < prefix.size(); ++i)
    {
        if (str[i] != prefix[i]) 
            return str;
    }

    if (i < str.size() && (str[i] == '/' || str[i] == '\\'))
        ++i;

    return str.substr(i);
}

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

void make_empty_file (
    const std::string& filename
)
{
    ofstream fout(filename.c_str());
    if (!fout)
        throw dlib::error("ERROR: Unable to open " + filename + " for writing.");
}

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

Davis King's avatar
Davis King committed
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
void create_new_dataset (
    const parser_type& parser
)
{
    using namespace dlib::image_dataset_metadata;

    const std::string filename = parser.option("c").argument();
    // make sure the file exists so we can use the get_parent_directory() command to
    // figure out it's parent directory.
    make_empty_file(filename);
    const std::string parent_dir = get_parent_directory(file(filename)).full_name();

    unsigned long depth = 0;
    if (parser.option("r"))
        depth = 30;

    dataset meta;
    meta.name = "imglab dataset";
    meta.comment = "Created by imglab tool.";
    for (unsigned long i = 0; i < parser.number_of_arguments(); ++i)
    {
        try
        {
            const string temp = strip_path(file(parser[i]).full_name(), parent_dir);
            meta.images.push_back(image(temp));
        }
        catch (dlib::file::file_not_found&)
        {
            // then parser[i] should be a directory

            std::vector<file> files = get_files_in_directory_tree(parser[i], 
                                                                  match_endings(".png .PNG .jpeg .JPEG .jpg .JPG .bmp .BMP .dng .DNG"),
                                                                  depth);
            sort(files.begin(), files.end());

            for (unsigned long j = 0; j < files.size(); ++j)
            {
                meta.images.push_back(image(strip_path(files[j].full_name(), parent_dir)));
            }
        }
    }

    save_image_dataset_metadata(meta, filename);
}

// ----------------------------------------------------------------------------------------
101

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
void print_all_labels (
    const dlib::image_dataset_metadata::dataset& data
)
{
    std::set<std::string> labels;
    for (unsigned long i = 0; i < data.images.size(); ++i)
    {
        for (unsigned long j = 0; j < data.images[i].boxes.size(); ++j)
        {
            labels.insert(data.images[i].boxes[j].label);
        }
    }

    for (std::set<std::string>::iterator i = labels.begin(); i != labels.end(); ++i)
    {
        if (i->size() != 0)
        {
            cout << *i << endl;
        }
    }
}

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

Davis King's avatar
Davis King committed
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
void rename_labels (
    dlib::image_dataset_metadata::dataset& data,
    const std::string& from,
    const std::string& to
)
{
    for (unsigned long i = 0; i < data.images.size(); ++i)
    {
        for (unsigned long j = 0; j < data.images[i].boxes.size(); ++j)
        {
            if (data.images[i].boxes[j].label == from)
                data.images[i].boxes[j].label = to;
        }
    }

}

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

145
146
147
148
149
150
151
152
153
int main(int argc, char** argv)
{
    try
    {

        parser_type parser;

        parser.add_option("h","Displays this information.");
        parser.add_option("c","Create an XML file named <arg> listing a set of images.",1);
154
        parser.add_option("r","Search directories recursively for images.");
155
        parser.add_option("l","List all the labels in the given XML file.");
Davis King's avatar
Davis King committed
156
        parser.add_option("rename", "Rename all labels of <arg1> to <arg2>.",2);
Davis King's avatar
Davis King committed
157
        parser.add_option("v","Display version.");
158
159
160

        parser.parse(argc, argv);

Davis King's avatar
Davis King committed
161
        const char* singles[] = {"h","c","r","l"};
162
        parser.check_one_time_options(singles);
163
        parser.check_sub_option("c", "r");
Davis King's avatar
Davis King committed
164
165
        parser.check_incompatible_options("c", "l");
        parser.check_incompatible_options("c", "rename");
166
167
168

        if (parser.option("h"))
        {
169
            cout << "Usage: imglab [options] <image files/directories or XML file>\n";
170
            parser.print_options(cout);
Davis King's avatar
Davis King committed
171
            cout << endl << endl;
172
173
174
            return EXIT_SUCCESS;
        }

Davis King's avatar
Davis King committed
175
176
177
178
179
180
181
182
183
        if (parser.option("v"))
        {
            cout << "imglab v" << VERSION 
                 << "\nCompiled: " << __TIME__ << " " << __DATE__ 
                 << "\nWritten by Davis King\n";
            cout << "Check for updates at http://dlib.net\n\n";
            return EXIT_SUCCESS;
        }

184
185
        if (parser.option("c"))
        {
Davis King's avatar
Davis King committed
186
            create_new_dataset(parser);
187
188
189
            return EXIT_SUCCESS;
        }

190
191
192
193
194
195
196
197
198
199
200
201
202
203
        if (parser.option("l"))
        {
            if (parser.number_of_arguments() != 1)
            {
                cerr << "The -l option requires you to give one XML file on the command line." << endl;
                return EXIT_FAILURE;
            }

            dlib::image_dataset_metadata::dataset data;
            load_image_dataset_metadata(data, parser[0]);
            print_all_labels(data);
            return EXIT_SUCCESS;
        }

Davis King's avatar
Davis King committed
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
        if (parser.option("rename"))
        {
            if (parser.number_of_arguments() != 1)
            {
                cerr << "The --rename option requires you to give one XML file on the command line." << endl;
                return EXIT_FAILURE;
            }

            dlib::image_dataset_metadata::dataset data;
            load_image_dataset_metadata(data, parser[0]);
            for (unsigned long i = 0; i < parser.option("rename").count(); ++i)
            {
                rename_labels(data, parser.option("rename").argument(0,i), parser.option("rename").argument(1,i));
            }
            save_image_dataset_metadata(data, parser[0]);
            return EXIT_SUCCESS;
        }

222
223
        if (parser.number_of_arguments() == 1)
        {
224
225
            metadata_editor editor(parser[0]);
            editor.wait_until_closed();
226
        }
227
228
229
    }
    catch (exception& e)
    {
230
        cerr << e.what() << endl;
231
232
233
234
        return EXIT_FAILURE;
    }
}

Davis King's avatar
Davis King committed
235
236
// ----------------------------------------------------------------------------------------