xref: /aosp_15_r20/external/armnn/tests/ImageCSVFileGenerator/ImageCSVFileGenerator.cpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1*89c4ff92SAndroid Build Coastguard Worker //
2*89c4ff92SAndroid Build Coastguard Worker // Copyright © 2017 Arm Ltd. All rights reserved.
3*89c4ff92SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
4*89c4ff92SAndroid Build Coastguard Worker //
5*89c4ff92SAndroid Build Coastguard Worker 
6*89c4ff92SAndroid Build Coastguard Worker #include <armnnUtils/Filesystem.hpp>
7*89c4ff92SAndroid Build Coastguard Worker #include <cxxopts/cxxopts.hpp>
8*89c4ff92SAndroid Build Coastguard Worker 
9*89c4ff92SAndroid Build Coastguard Worker #include <algorithm>
10*89c4ff92SAndroid Build Coastguard Worker #include <fstream>
11*89c4ff92SAndroid Build Coastguard Worker #include <iostream>
12*89c4ff92SAndroid Build Coastguard Worker #include <string>
13*89c4ff92SAndroid Build Coastguard Worker 
14*89c4ff92SAndroid Build Coastguard Worker namespace
15*89c4ff92SAndroid Build Coastguard Worker {
16*89c4ff92SAndroid Build Coastguard Worker 
17*89c4ff92SAndroid Build Coastguard Worker // parses the command line to extract
18*89c4ff92SAndroid Build Coastguard Worker // * the directory -i to look through .raw files from (must exist)
19*89c4ff92SAndroid Build Coastguard Worker // * the name of the file -o the output CSV file path (must not already exist)
20*89c4ff92SAndroid Build Coastguard Worker class CommandLineProcessor
21*89c4ff92SAndroid Build Coastguard Worker {
22*89c4ff92SAndroid Build Coastguard Worker public:
ParseOptions(cxxopts::ParseResult & result)23*89c4ff92SAndroid Build Coastguard Worker     bool ParseOptions(cxxopts::ParseResult& result)
24*89c4ff92SAndroid Build Coastguard Worker     {
25*89c4ff92SAndroid Build Coastguard Worker         // indir is mandatory, dir could possibly be changed.
26*89c4ff92SAndroid Build Coastguard Worker         if (result.count("indir"))
27*89c4ff92SAndroid Build Coastguard Worker         {
28*89c4ff92SAndroid Build Coastguard Worker             std::string dir = result["indir"].as<std::string>();
29*89c4ff92SAndroid Build Coastguard Worker 
30*89c4ff92SAndroid Build Coastguard Worker             if (!ValidateDirectory(dir))
31*89c4ff92SAndroid Build Coastguard Worker             {
32*89c4ff92SAndroid Build Coastguard Worker                 return false;
33*89c4ff92SAndroid Build Coastguard Worker             }
34*89c4ff92SAndroid Build Coastguard Worker 
35*89c4ff92SAndroid Build Coastguard Worker             m_InputDirectory = dir;
36*89c4ff92SAndroid Build Coastguard Worker         }
37*89c4ff92SAndroid Build Coastguard Worker         else
38*89c4ff92SAndroid Build Coastguard Worker         {
39*89c4ff92SAndroid Build Coastguard Worker             std::cerr << "-i/--indir parameter is mandatory." << std::endl;
40*89c4ff92SAndroid Build Coastguard Worker             return false;
41*89c4ff92SAndroid Build Coastguard Worker         }
42*89c4ff92SAndroid Build Coastguard Worker 
43*89c4ff92SAndroid Build Coastguard Worker         // outfile is mandatory
44*89c4ff92SAndroid Build Coastguard Worker         if (result.count("outfile"))
45*89c4ff92SAndroid Build Coastguard Worker         {
46*89c4ff92SAndroid Build Coastguard Worker             if (!ValidateOutputFile(result["outfile"].as<std::string>()))
47*89c4ff92SAndroid Build Coastguard Worker             {
48*89c4ff92SAndroid Build Coastguard Worker                 return false;
49*89c4ff92SAndroid Build Coastguard Worker             }
50*89c4ff92SAndroid Build Coastguard Worker         }
51*89c4ff92SAndroid Build Coastguard Worker         else
52*89c4ff92SAndroid Build Coastguard Worker         {
53*89c4ff92SAndroid Build Coastguard Worker             std::cerr << "-o/--outfile parameter is mandatory." << std::endl;
54*89c4ff92SAndroid Build Coastguard Worker             return false;
55*89c4ff92SAndroid Build Coastguard Worker         }
56*89c4ff92SAndroid Build Coastguard Worker 
57*89c4ff92SAndroid Build Coastguard Worker         if (result.count("layer-binding-id"))
58*89c4ff92SAndroid Build Coastguard Worker         {
59*89c4ff92SAndroid Build Coastguard Worker             if(!ValidateBindingId(result["layer-binding-id"].as<std::string>()))
60*89c4ff92SAndroid Build Coastguard Worker             {
61*89c4ff92SAndroid Build Coastguard Worker                 return false;
62*89c4ff92SAndroid Build Coastguard Worker             }
63*89c4ff92SAndroid Build Coastguard Worker         }
64*89c4ff92SAndroid Build Coastguard Worker         return true;
65*89c4ff92SAndroid Build Coastguard Worker     }
66*89c4ff92SAndroid Build Coastguard Worker 
ValidateDirectory(std::string & dir)67*89c4ff92SAndroid Build Coastguard Worker     bool ValidateDirectory(std::string& dir)
68*89c4ff92SAndroid Build Coastguard Worker     {
69*89c4ff92SAndroid Build Coastguard Worker         if (dir.empty())
70*89c4ff92SAndroid Build Coastguard Worker         {
71*89c4ff92SAndroid Build Coastguard Worker             std::cerr << "No directory specified" << std::endl;
72*89c4ff92SAndroid Build Coastguard Worker             return false;
73*89c4ff92SAndroid Build Coastguard Worker         }
74*89c4ff92SAndroid Build Coastguard Worker 
75*89c4ff92SAndroid Build Coastguard Worker         if (dir[dir.length() - 1] != '/')
76*89c4ff92SAndroid Build Coastguard Worker         {
77*89c4ff92SAndroid Build Coastguard Worker             dir += "/";
78*89c4ff92SAndroid Build Coastguard Worker         }
79*89c4ff92SAndroid Build Coastguard Worker 
80*89c4ff92SAndroid Build Coastguard Worker         if (!fs::exists(dir))
81*89c4ff92SAndroid Build Coastguard Worker         {
82*89c4ff92SAndroid Build Coastguard Worker             std::cerr << "Directory [" << dir << "] does not exist" << std::endl;
83*89c4ff92SAndroid Build Coastguard Worker             return false;
84*89c4ff92SAndroid Build Coastguard Worker         }
85*89c4ff92SAndroid Build Coastguard Worker 
86*89c4ff92SAndroid Build Coastguard Worker         if (!fs::is_directory(dir))
87*89c4ff92SAndroid Build Coastguard Worker         {
88*89c4ff92SAndroid Build Coastguard Worker             std::cerr << "Given directory [" << dir << "] is not a directory" << std::endl;
89*89c4ff92SAndroid Build Coastguard Worker             return false;
90*89c4ff92SAndroid Build Coastguard Worker         }
91*89c4ff92SAndroid Build Coastguard Worker 
92*89c4ff92SAndroid Build Coastguard Worker         return true;
93*89c4ff92SAndroid Build Coastguard Worker     }
94*89c4ff92SAndroid Build Coastguard Worker 
ValidateOutputFile(const std::string & outputFileName)95*89c4ff92SAndroid Build Coastguard Worker     bool ValidateOutputFile(const std::string& outputFileName)
96*89c4ff92SAndroid Build Coastguard Worker     {
97*89c4ff92SAndroid Build Coastguard Worker         if (outputFileName.empty())
98*89c4ff92SAndroid Build Coastguard Worker         {
99*89c4ff92SAndroid Build Coastguard Worker             std::cerr << "No output file name specified" << std::endl;
100*89c4ff92SAndroid Build Coastguard Worker             return false;
101*89c4ff92SAndroid Build Coastguard Worker         }
102*89c4ff92SAndroid Build Coastguard Worker 
103*89c4ff92SAndroid Build Coastguard Worker         if (fs::exists(outputFileName))
104*89c4ff92SAndroid Build Coastguard Worker         {
105*89c4ff92SAndroid Build Coastguard Worker             std::cerr << "Output file [" << outputFileName << "] already exists" << std::endl;
106*89c4ff92SAndroid Build Coastguard Worker             return false;
107*89c4ff92SAndroid Build Coastguard Worker         }
108*89c4ff92SAndroid Build Coastguard Worker 
109*89c4ff92SAndroid Build Coastguard Worker         if (fs::is_directory(outputFileName))
110*89c4ff92SAndroid Build Coastguard Worker         {
111*89c4ff92SAndroid Build Coastguard Worker             std::cerr << "Output file [" << outputFileName << "] is a directory" << std::endl;
112*89c4ff92SAndroid Build Coastguard Worker             return false;
113*89c4ff92SAndroid Build Coastguard Worker         }
114*89c4ff92SAndroid Build Coastguard Worker 
115*89c4ff92SAndroid Build Coastguard Worker         fs::path outputPath(outputFileName);
116*89c4ff92SAndroid Build Coastguard Worker         if (!fs::exists(outputPath.parent_path()))
117*89c4ff92SAndroid Build Coastguard Worker         {
118*89c4ff92SAndroid Build Coastguard Worker             std::cerr << "Directory [" << outputPath.parent_path().c_str() << "] does not exist" << std::endl;
119*89c4ff92SAndroid Build Coastguard Worker             return false;
120*89c4ff92SAndroid Build Coastguard Worker         }
121*89c4ff92SAndroid Build Coastguard Worker 
122*89c4ff92SAndroid Build Coastguard Worker         return true;
123*89c4ff92SAndroid Build Coastguard Worker     }
124*89c4ff92SAndroid Build Coastguard Worker 
ValidateBindingId(const std::string & id)125*89c4ff92SAndroid Build Coastguard Worker     bool ValidateBindingId(const std::string& id)
126*89c4ff92SAndroid Build Coastguard Worker     {
127*89c4ff92SAndroid Build Coastguard Worker         if (!std::all_of(id.begin(), id.end(), ::isdigit))
128*89c4ff92SAndroid Build Coastguard Worker         {
129*89c4ff92SAndroid Build Coastguard Worker             std::cerr << "Invalid input binding Id" << std::endl;
130*89c4ff92SAndroid Build Coastguard Worker             return false;
131*89c4ff92SAndroid Build Coastguard Worker         }
132*89c4ff92SAndroid Build Coastguard Worker 
133*89c4ff92SAndroid Build Coastguard Worker         return true;
134*89c4ff92SAndroid Build Coastguard Worker     }
135*89c4ff92SAndroid Build Coastguard Worker 
ProcessCommandLine(int argc,char * argv[])136*89c4ff92SAndroid Build Coastguard Worker     bool ProcessCommandLine(int argc, char* argv[])
137*89c4ff92SAndroid Build Coastguard Worker     {
138*89c4ff92SAndroid Build Coastguard Worker         try
139*89c4ff92SAndroid Build Coastguard Worker         {
140*89c4ff92SAndroid Build Coastguard Worker             cxxopts::Options options("ImageCSVFileGenerator",
141*89c4ff92SAndroid Build Coastguard Worker                                      "Program for creating a CSV file that "
142*89c4ff92SAndroid Build Coastguard Worker                                      "contains a list of .raw tensor files. "
143*89c4ff92SAndroid Build Coastguard Worker                                      "These .raw tensor files can be generated using the ImageTensorGenerator");
144*89c4ff92SAndroid Build Coastguard Worker 
145*89c4ff92SAndroid Build Coastguard Worker             options.add_options()
146*89c4ff92SAndroid Build Coastguard Worker                 ("h,help", "Display help messages")
147*89c4ff92SAndroid Build Coastguard Worker                 ("i,indir",
148*89c4ff92SAndroid Build Coastguard Worker                     "Directory that .raw files are stored in",
149*89c4ff92SAndroid Build Coastguard Worker                     cxxopts::value<std::string>(m_InputDirectory))
150*89c4ff92SAndroid Build Coastguard Worker                 ("o,outfile",
151*89c4ff92SAndroid Build Coastguard Worker                     "Output CSV file path",
152*89c4ff92SAndroid Build Coastguard Worker                     cxxopts::value<std::string>(m_OutputFileName))
153*89c4ff92SAndroid Build Coastguard Worker                 ("l, layer-binding-id",
154*89c4ff92SAndroid Build Coastguard Worker                     "Input layer binding Id, Defaults to 0",
155*89c4ff92SAndroid Build Coastguard Worker                     cxxopts::value<std::string>(m_InputBindingId)->default_value("0"));
156*89c4ff92SAndroid Build Coastguard Worker 
157*89c4ff92SAndroid Build Coastguard Worker             auto result = options.parse(argc, argv);
158*89c4ff92SAndroid Build Coastguard Worker 
159*89c4ff92SAndroid Build Coastguard Worker             if (result.count("help"))
160*89c4ff92SAndroid Build Coastguard Worker             {
161*89c4ff92SAndroid Build Coastguard Worker                 std::cout << options.help() << std::endl;
162*89c4ff92SAndroid Build Coastguard Worker                 return false;
163*89c4ff92SAndroid Build Coastguard Worker             }
164*89c4ff92SAndroid Build Coastguard Worker 
165*89c4ff92SAndroid Build Coastguard Worker             // Check for mandatory parameters and validate inputs
166*89c4ff92SAndroid Build Coastguard Worker             if(!ParseOptions(result)){
167*89c4ff92SAndroid Build Coastguard Worker                 return false;
168*89c4ff92SAndroid Build Coastguard Worker             }
169*89c4ff92SAndroid Build Coastguard Worker         }
170*89c4ff92SAndroid Build Coastguard Worker         catch (const cxxopts::OptionException& e)
171*89c4ff92SAndroid Build Coastguard Worker         {
172*89c4ff92SAndroid Build Coastguard Worker             std::cerr << e.what() << std::endl << std::endl;
173*89c4ff92SAndroid Build Coastguard Worker             return false;
174*89c4ff92SAndroid Build Coastguard Worker         }
175*89c4ff92SAndroid Build Coastguard Worker         catch (const std::exception& e)
176*89c4ff92SAndroid Build Coastguard Worker         {
177*89c4ff92SAndroid Build Coastguard Worker             std::cerr << "Fatal internal error: [" << e.what() << "]" << std::endl;
178*89c4ff92SAndroid Build Coastguard Worker             return false;
179*89c4ff92SAndroid Build Coastguard Worker         }
180*89c4ff92SAndroid Build Coastguard Worker 
181*89c4ff92SAndroid Build Coastguard Worker         return true;
182*89c4ff92SAndroid Build Coastguard Worker     }
183*89c4ff92SAndroid Build Coastguard Worker 
GetInputDirectory()184*89c4ff92SAndroid Build Coastguard Worker     std::string GetInputDirectory() {return m_InputDirectory;}
GetOutputFileName()185*89c4ff92SAndroid Build Coastguard Worker     std::string GetOutputFileName() {return m_OutputFileName;}
GetInputBindingId()186*89c4ff92SAndroid Build Coastguard Worker     std::string GetInputBindingId() {return m_InputBindingId;}
187*89c4ff92SAndroid Build Coastguard Worker 
188*89c4ff92SAndroid Build Coastguard Worker private:
189*89c4ff92SAndroid Build Coastguard Worker     std::string m_InputDirectory;
190*89c4ff92SAndroid Build Coastguard Worker     std::string m_OutputFileName;
191*89c4ff92SAndroid Build Coastguard Worker     std::string m_InputBindingId;
192*89c4ff92SAndroid Build Coastguard Worker };
193*89c4ff92SAndroid Build Coastguard Worker 
194*89c4ff92SAndroid Build Coastguard Worker } // namespace anonymous
195*89c4ff92SAndroid Build Coastguard Worker 
main(int argc,char * argv[])196*89c4ff92SAndroid Build Coastguard Worker int main(int argc, char* argv[])
197*89c4ff92SAndroid Build Coastguard Worker {
198*89c4ff92SAndroid Build Coastguard Worker     CommandLineProcessor cmdline;
199*89c4ff92SAndroid Build Coastguard Worker     if (!cmdline.ProcessCommandLine(argc, argv))
200*89c4ff92SAndroid Build Coastguard Worker     {
201*89c4ff92SAndroid Build Coastguard Worker         return -1;
202*89c4ff92SAndroid Build Coastguard Worker     }
203*89c4ff92SAndroid Build Coastguard Worker 
204*89c4ff92SAndroid Build Coastguard Worker     const std::string fileFormat(".raw");
205*89c4ff92SAndroid Build Coastguard Worker 
206*89c4ff92SAndroid Build Coastguard Worker     const std::string rawDirectory(cmdline.GetInputDirectory());
207*89c4ff92SAndroid Build Coastguard Worker     const std::string outputPath(cmdline.GetOutputFileName());
208*89c4ff92SAndroid Build Coastguard Worker     const std::string bindingId(cmdline.GetInputBindingId());
209*89c4ff92SAndroid Build Coastguard Worker 
210*89c4ff92SAndroid Build Coastguard Worker     std::vector<fs::path> rawFiles;
211*89c4ff92SAndroid Build Coastguard Worker     for (auto& entry : fs::directory_iterator(rawDirectory))
212*89c4ff92SAndroid Build Coastguard Worker     {
213*89c4ff92SAndroid Build Coastguard Worker         if (entry.path().extension().c_str() == fileFormat)
214*89c4ff92SAndroid Build Coastguard Worker         {
215*89c4ff92SAndroid Build Coastguard Worker             rawFiles.push_back(entry.path());
216*89c4ff92SAndroid Build Coastguard Worker         }
217*89c4ff92SAndroid Build Coastguard Worker     }
218*89c4ff92SAndroid Build Coastguard Worker 
219*89c4ff92SAndroid Build Coastguard Worker     if (!rawFiles.empty())
220*89c4ff92SAndroid Build Coastguard Worker     {
221*89c4ff92SAndroid Build Coastguard Worker         unsigned int pass = 0;
222*89c4ff92SAndroid Build Coastguard Worker         std::ofstream refinementData;
223*89c4ff92SAndroid Build Coastguard Worker         refinementData.open(outputPath, std::ofstream::out);
224*89c4ff92SAndroid Build Coastguard Worker         if (refinementData.is_open())
225*89c4ff92SAndroid Build Coastguard Worker         {
226*89c4ff92SAndroid Build Coastguard Worker             for (auto const& raw : rawFiles)
227*89c4ff92SAndroid Build Coastguard Worker             {
228*89c4ff92SAndroid Build Coastguard Worker                 refinementData << pass << ", " << bindingId << ", " << raw.c_str() << "\n";
229*89c4ff92SAndroid Build Coastguard Worker                 if (!refinementData)
230*89c4ff92SAndroid Build Coastguard Worker                 {
231*89c4ff92SAndroid Build Coastguard Worker                     std::cerr << "Failed to write to output file: " << outputPath << std::endl;
232*89c4ff92SAndroid Build Coastguard Worker                     continue;
233*89c4ff92SAndroid Build Coastguard Worker                 }
234*89c4ff92SAndroid Build Coastguard Worker                 ++pass;
235*89c4ff92SAndroid Build Coastguard Worker             }
236*89c4ff92SAndroid Build Coastguard Worker             refinementData.close();
237*89c4ff92SAndroid Build Coastguard Worker         }
238*89c4ff92SAndroid Build Coastguard Worker         else
239*89c4ff92SAndroid Build Coastguard Worker         {
240*89c4ff92SAndroid Build Coastguard Worker             std::cerr << "Failed to open output file: " << outputPath << std::endl;
241*89c4ff92SAndroid Build Coastguard Worker             return -1;
242*89c4ff92SAndroid Build Coastguard Worker         }
243*89c4ff92SAndroid Build Coastguard Worker     }
244*89c4ff92SAndroid Build Coastguard Worker     else
245*89c4ff92SAndroid Build Coastguard Worker     {
246*89c4ff92SAndroid Build Coastguard Worker         std::cerr << "No matching files with the \".raw\" extension found in the directory: "
247*89c4ff92SAndroid Build Coastguard Worker                   << rawDirectory << std::endl;
248*89c4ff92SAndroid Build Coastguard Worker         return -1;
249*89c4ff92SAndroid Build Coastguard Worker     }
250*89c4ff92SAndroid Build Coastguard Worker 
251*89c4ff92SAndroid Build Coastguard Worker     return 0;
252*89c4ff92SAndroid Build Coastguard Worker }