main.cpp 6.79 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");
Davis King's avatar
Davis King committed
166
        parser.check_incompatible_options("l", "rename");
167
168
169

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

Davis King's avatar
Davis King committed
176
177
178
179
180
181
182
183
184
        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;
        }

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

191
192
193
194
195
196
197
198
199
200
201
202
203
204
        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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
        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;
        }

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

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