2ce28d14740dd34500f70322fd4b3abde652eff7
[platform/upstream/dldt.git] / inference-engine / samples / validation_app / classification_set_generator.cpp
1 // Copyright (C) 2018 Intel Corporation
2 //
3 // SPDX-License-Identifier: Apache-2.0
4 //
5
6 #include "classification_set_generator.hpp"
7
8 #include <algorithm>
9 #include <fstream>
10 #include <iostream>
11 #include <list>
12 #include <map>
13 #include <string>
14 #include <utility>
15 #include <vector>
16
17 #include "user_exception.hpp"
18 #include "details/ie_exception.hpp"
19
20 #ifdef _WIN32
21 # include "w_dirent.h"
22 #else
23 # include <sys/stat.h>
24 # include <dirent.h>
25 #endif
26
27 #include "../common/samples/common.hpp"
28
29 /**
30  * @brief Gets path part of a filename including separator
31  * @param filepath - filename to extract path part from
32  * @return string with path part of the filename
33  */
34 inline std::string folderOf(const std::string &filepath) {
35     auto pos = filepath.rfind("/");
36     if (pos == std::string::npos) pos = filepath.rfind("\\");
37     if (pos == std::string::npos) return "";
38     return filepath.substr(0, pos + 1);
39 }
40
41 void readFile(std::string filename, std::function<void(std::string&, int lineNumber)> perLine) {
42     std::ifstream inputFile;
43     inputFile.open(filename, std::ios::in);
44     std::string strLine = "";
45
46     if (!inputFile.is_open())
47         THROW_IE_EXCEPTION << "Cannot open file: " << filename;
48
49     size_t lineNumber = 0;
50     while (std::getline(inputFile, strLine)) {
51         lineNumber++;
52         perLine(strLine, lineNumber);
53     }
54 }
55
56 std::map<std::string, int> ClassificationSetGenerator::readLabels(const std::string& labels) {
57     _classes.clear();
58     int i = 0;
59
60     readFile(labels, [&](std::string& line, size_t lineNumber) {
61         trim(line);
62         _classes[line] = i++;
63     });
64
65     return _classes;
66 }
67
68 std::string getFullName(const std::string& name, const std::string& dir) {
69     return dir + "/" + name;
70 }
71
72 std::list<std::string> ClassificationSetGenerator::getDirContents(const std::string& dir, bool includePath) {
73     struct stat sb;
74     if (stat(dir.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
75         return std::list<std::string>();
76         // THROW_USER_EXCEPTION(1) << "Can't read contents of directory " << dir << ". It isn't a directory or not accessible";
77     }
78
79     std::list<std::string> list;
80     DIR *dp;
81     dp = opendir(dir.c_str());
82     if (dp == nullptr) {
83         THROW_USER_EXCEPTION(1) << "Can't open directory " << dir;
84     }
85
86     struct dirent *ep;
87     while (nullptr != (ep = readdir(dp))) {
88         std::string fileName = ep->d_name;
89         if (fileName == "." || fileName == "..") continue;
90         list.push_back(includePath ? getFullName(ep->d_name, dir) : ep->d_name);
91     }
92     closedir(dp);
93     return list;
94 }
95
96 std::vector<std::pair<int, std::string>> ClassificationSetGenerator::validationMapFromTxt(const std::string& file) {
97     std::string ext = fileExt(file);
98     if (ext != "txt") {
99         THROW_USER_EXCEPTION(1) << "Unknown dataset data file format: " << ext << "";
100     }
101
102     std::string dir = folderOf(file);
103     std::vector<std::pair<int, std::string>> validationMap;
104     std::string imgPath = "";
105     int classId = -1;
106
107     readFile(file, [&](std::string& line, size_t lineNumber) {
108         trim(line);
109         size_t pos = line.rfind(" ");
110         if (pos == std::string::npos) {
111             THROW_USER_EXCEPTION(1) << "Bad file format! Cannot parse line " << lineNumber << ":\n> " << line;
112         }
113         try {
114             classId = std::stoi(line.substr(pos + 1));
115         } catch (const std::invalid_argument& e) {
116             THROW_USER_EXCEPTION(1) << "Invalid class id specified at line " << lineNumber << ":\n> " << line;
117         }
118         imgPath = line.substr(0, pos);
119         validationMap.push_back({ classId, dir + imgPath });
120     });
121
122     return validationMap;
123 }
124
125 std::vector<std::pair<int, std::string>> ClassificationSetGenerator::validationMapFromFolder(const std::string& dir) {
126     std::vector<std::pair<int, std::string>> validationMap;
127     std::list<std::string> validation_labels = getDirContents(dir, false);
128
129     for (auto& label : validation_labels) {
130         auto val = _classes.find(label);
131         if (val == _classes.end()) continue;
132
133         int id = val->second;
134         for (auto& image : getDirContents(getFullName(label, dir))) {
135             validationMap.push_back({ id + 1, image });        // [CVS-8200] line in .labels file is counted from 0, but classes are counted from 1
136         }
137     }
138     return validationMap;
139 }
140
141 std::vector<std::pair<int, std::string>> ClassificationSetGenerator::getValidationMap(const std::string& path) {
142     struct stat sb;
143     if (stat(path.c_str(), &sb) == 0) {
144         if (S_ISDIR(sb.st_mode)) {
145             return validationMapFromFolder(path);
146         } else {
147             return validationMapFromTxt(path);
148         }
149     } else {
150         if (errno == ENOENT || errno == EINVAL || errno == EACCES) {
151             THROW_USER_EXCEPTION(3) << "The specified path \"" << path << "\" can not be found or accessed";
152         }
153     }
154     return{};
155 }