ArmNN
 22.08
TfLiteYoloV3Big-Armnn.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2020 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
7 
8 #include "NMS.hpp"
9 
10 #include <stb/stb_image.h>
11 
12 #include <armnn/INetwork.hpp>
13 #include <armnn/IRuntime.hpp>
14 #include <armnn/Logging.hpp>
16 
17 #include <cxxopts/cxxopts.hpp>
18 #include <ghc/filesystem.hpp>
19 
20 #include <chrono>
21 #include <fstream>
22 #include <iostream>
23 #include <cmath>
24 
25 using namespace armnnTfLiteParser;
26 using namespace armnn;
27 
28 static const int OPEN_FILE_ERROR = -2;
29 static const int OPTIMIZE_NETWORK_ERROR = -3;
30 static const int LOAD_NETWORK_ERROR = -4;
31 static const int LOAD_IMAGE_ERROR = -5;
32 static const int GENERAL_ERROR = -100;
33 
34 #define CHECK_OK(v) \
35  do { \
36  try { \
37  auto r_local = v; \
38  if (r_local != 0) { return r_local;} \
39  } \
40  catch (const armnn::Exception& e) \
41  { \
42  ARMNN_LOG(error) << "Oops: " << e.what(); \
43  return GENERAL_ERROR; \
44  } \
45  } while(0)
46 
47 
48 
49 template<typename TContainer>
50 inline armnn::InputTensors MakeInputTensors(const std::vector<armnn::BindingPointInfo>& inputBindings,
51  const std::vector<std::reference_wrapper<TContainer>>& inputDataContainers)
52 {
53  armnn::InputTensors inputTensors;
54 
55  const size_t numInputs = inputBindings.size();
56  if (numInputs != inputDataContainers.size())
57  {
58  throw armnn::Exception("Mismatching vectors");
59  }
60 
61  for (size_t i = 0; i < numInputs; i++)
62  {
63  const armnn::BindingPointInfo& inputBinding = inputBindings[i];
64  const TContainer& inputData = inputDataContainers[i].get();
65 
66  armnn::ConstTensor inputTensor(inputBinding.second, inputData.data());
67  inputTensors.push_back(std::make_pair(inputBinding.first, inputTensor));
68  }
69 
70  return inputTensors;
71 }
72 
73 template<typename TContainer>
75  const std::vector<armnn::BindingPointInfo>& outputBindings,
76  const std::vector<std::reference_wrapper<TContainer>>& outputDataContainers)
77 {
78  armnn::OutputTensors outputTensors;
79 
80  const size_t numOutputs = outputBindings.size();
81  if (numOutputs != outputDataContainers.size())
82  {
83  throw armnn::Exception("Mismatching vectors");
84  }
85 
86  outputTensors.reserve(numOutputs);
87 
88  for (size_t i = 0; i < numOutputs; i++)
89  {
90  const armnn::BindingPointInfo& outputBinding = outputBindings[i];
91  const TContainer& outputData = outputDataContainers[i].get();
92 
93  armnn::Tensor outputTensor(outputBinding.second, const_cast<float*>(outputData.data()));
94  outputTensors.push_back(std::make_pair(outputBinding.first, outputTensor));
95  }
96 
97  return outputTensors;
98 }
99 
100 #define S_BOOL(name) enum class name {False=0, True=1};
101 
106 
107 int LoadModel(const char* filename,
108  ITfLiteParser& parser,
109  IRuntime& runtime,
110  NetworkId& networkId,
111  const std::vector<BackendId>& backendPreferences,
112  ImportMemory enableImport,
113  DumpToDot dumpToDot)
114 {
115  std::ifstream stream(filename, std::ios::in | std::ios::binary);
116  if (!stream.is_open())
117  {
118  ARMNN_LOG(error) << "Could not open model: " << filename;
119  return OPEN_FILE_ERROR;
120  }
121 
122  std::vector<uint8_t> contents((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
123  stream.close();
124 
125  auto model = parser.CreateNetworkFromBinary(contents);
126  contents.clear();
127  ARMNN_LOG(debug) << "Model loaded ok: " << filename;
128 
129  // Optimize backbone model
130  OptimizerOptions options;
131  options.m_ImportEnabled = enableImport != ImportMemory::False;
132  auto optimizedModel = Optimize(*model, backendPreferences, runtime.GetDeviceSpec(), options);
133  if (!optimizedModel)
134  {
135  ARMNN_LOG(fatal) << "Could not optimize the model:" << filename;
136  return OPTIMIZE_NETWORK_ERROR;
137  }
138 
139  if (dumpToDot != DumpToDot::False)
140  {
141  std::stringstream ss;
142  ss << filename << ".dot";
143  std::ofstream dotStream(ss.str().c_str(), std::ofstream::out);
144  optimizedModel->SerializeToDot(dotStream);
145  dotStream.close();
146  }
147  // Load model into runtime
148  {
149  std::string errorMessage;
150 
153  INetworkProperties modelProps(false, memSource, memSource);
154  Status status = runtime.LoadNetwork(networkId, std::move(optimizedModel), errorMessage, modelProps);
155  if (status != Status::Success)
156  {
157  ARMNN_LOG(fatal) << "Could not load " << filename << " model into runtime: " << errorMessage;
158  return LOAD_NETWORK_ERROR;
159  }
160  }
161 
162  return 0;
163 }
164 
165 std::vector<float> LoadImage(const char* filename)
166 {
167  if (strlen(filename) == 0)
168  {
169  return std::vector<float>(1920*10180*3, 0.0f);
170  }
171  struct Memory
172  {
173  ~Memory() {stbi_image_free(m_Data);}
174  bool IsLoaded() const { return m_Data != nullptr;}
175 
176  unsigned char* m_Data;
177  };
178 
179  std::vector<float> image;
180 
181  int width;
182  int height;
183  int channels;
184 
185  Memory mem = {stbi_load(filename, &width, &height, &channels, 3)};
186  if (!mem.IsLoaded())
187  {
188  ARMNN_LOG(error) << "Could not load input image file: " << filename;
189  return image;
190  }
191 
192  if (width != 1920 || height != 1080 || channels != 3)
193  {
194  ARMNN_LOG(error) << "Input image has wong dimension: " << width << "x" << height << "x" << channels << ". "
195  " Expected 1920x1080x3.";
196  return image;
197  }
198 
199  image.resize(1920*1080*3);
200 
201  // Expand to float. Does this need de-gamma?
202  for (unsigned int idx=0; idx <= 1920*1080*3; idx++)
203  {
204  image[idx] = static_cast<float>(mem.m_Data[idx]) /255.0f;
205  }
206 
207  return image;
208 }
209 
210 
211 bool ValidateFilePath(std::string& file, ExpectFile expectFile)
212 {
213  if (!ghc::filesystem::exists(file))
214  {
215  std::cerr << "Given file path " << file << " does not exist" << std::endl;
216  return false;
217  }
218  if (!ghc::filesystem::is_regular_file(file) && expectFile == ExpectFile::True)
219  {
220  std::cerr << "Given file path " << file << " is not a regular file" << std::endl;
221  return false;
222  }
223  return true;
224 }
225 
226 void CheckAccuracy(std::vector<float>* toDetector0, std::vector<float>* toDetector1,
227  std::vector<float>* toDetector2, std::vector<float>* detectorOutput,
228  const std::vector<yolov3::Detection>& nmsOut, const std::vector<std::string>& filePaths)
229 {
230  std::ifstream pathStream;
231  std::vector<float> expected;
232  std::vector<std::vector<float>*> outputs;
233  float compare = 0;
234  unsigned int count = 0;
235 
236  //Push back output vectors from inference for use in loop
237  outputs.push_back(toDetector0);
238  outputs.push_back(toDetector1);
239  outputs.push_back(toDetector2);
240  outputs.push_back(detectorOutput);
241 
242  for (unsigned int i = 0; i < outputs.size(); ++i)
243  {
244  // Reading expected output files and assigning them to @expected. Close and Clear to reuse stream and clean RAM
245  pathStream.open(filePaths[i]);
246  if (!pathStream.is_open())
247  {
248  ARMNN_LOG(error) << "Expected output file can not be opened: " << filePaths[i];
249  continue;
250  }
251 
252  expected.assign(std::istream_iterator<float>(pathStream), {});
253  pathStream.close();
254  pathStream.clear();
255 
256  // Ensure each vector is the same length
257  if (expected.size() != outputs[i]->size())
258  {
259  ARMNN_LOG(error) << "Expected output size does not match actual output size: " << filePaths[i];
260  }
261  else
262  {
263  count = 0;
264 
265  // Compare abs(difference) with tolerance to check for value by value equality
266  for (unsigned int j = 0; j < outputs[i]->size(); ++j)
267  {
268  compare = std::abs(expected[j] - outputs[i]->at(j));
269  if (compare > 0.001f)
270  {
271  count++;
272  }
273  }
274  if (count > 0)
275  {
276  ARMNN_LOG(error) << count << " output(s) do not match expected values in: " << filePaths[i];
277  }
278  }
279  }
280 
281  pathStream.open(filePaths[4]);
282  if (!pathStream.is_open())
283  {
284  ARMNN_LOG(error) << "Expected output file can not be opened: " << filePaths[4];
285  }
286  else
287  {
288  expected.assign(std::istream_iterator<float>(pathStream), {});
289  pathStream.close();
290  pathStream.clear();
291  unsigned int y = 0;
292  unsigned int numOfMember = 6;
293  std::vector<float> intermediate;
294 
295  for (auto& detection: nmsOut)
296  {
297  for (unsigned int x = y * numOfMember; x < ((y * numOfMember) + numOfMember); ++x)
298  {
299  intermediate.push_back(expected[x]);
300  }
301  if (!yolov3::compare_detection(detection, intermediate))
302  {
303  ARMNN_LOG(error) << "Expected NMS output does not match: Detection " << y + 1;
304  }
305  intermediate.clear();
306  y++;
307  }
308  }
309 }
310 
311 struct ParseArgs
312 {
313  ParseArgs(int ac, char *av[]) : options{"TfLiteYoloV3Big-Armnn",
314  "Executes YoloV3Big using ArmNN. YoloV3Big consists "
315  "of 3 parts: A backbone TfLite model, a detector TfLite "
316  "model, and None Maximum Suppression. All parts are "
317  "executed successively."}
318  {
319  options.add_options()
320  ("b,backbone-path",
321  "File path where the TfLite model for the yoloV3big backbone "
322  "can be found e.g. mydir/yoloV3big_backbone.tflite",
323  cxxopts::value<std::string>())
324 
325  ("c,comparison-files",
326  "Defines the expected outputs for the model "
327  "of yoloV3big e.g. 'mydir/file1.txt,mydir/file2.txt,mydir/file3.txt,mydir/file4.txt'->InputToDetector1"
328  " will be tried first then InputToDetector2 then InputToDetector3 then the Detector Output and finally"
329  " the NMS output. NOTE: Files are passed as comma separated list without whitespaces.",
330  cxxopts::value<std::vector<std::string>>()->default_value({}))
331 
332  ("d,detector-path",
333  "File path where the TfLite model for the yoloV3big "
334  "detector can be found e.g.'mydir/yoloV3big_detector.tflite'",
335  cxxopts::value<std::string>())
336 
337  ("h,help", "Produce help message")
338 
339  ("i,image-path",
340  "File path to a 1080x1920 jpg image that should be "
341  "processed e.g. 'mydir/example_img_180_1920.jpg'",
342  cxxopts::value<std::string>())
343 
344  ("B,preferred-backends-backbone",
345  "Defines the preferred backends to run the backbone model "
346  "of yoloV3big e.g. 'GpuAcc,CpuRef' -> GpuAcc will be tried "
347  "first before falling back to CpuRef. NOTE: Backends are passed "
348  "as comma separated list without whitespaces.",
349  cxxopts::value<std::vector<std::string>>()->default_value("GpuAcc,CpuRef"))
350 
351  ("D,preferred-backends-detector",
352  "Defines the preferred backends to run the detector model "
353  "of yoloV3big e.g. 'CpuAcc,CpuRef' -> CpuAcc will be tried "
354  "first before falling back to CpuRef. NOTE: Backends are passed "
355  "as comma separated list without whitespaces.",
356  cxxopts::value<std::vector<std::string>>()->default_value("CpuAcc,CpuRef"))
357 
358  ("M, model-to-dot",
359  "Dump the optimized model to a dot file for debugging/analysis",
360  cxxopts::value<bool>()->default_value("false"))
361 
362  ("Y, dynamic-backends-path",
363  "Define a path from which to load any dynamic backends.",
364  cxxopts::value<std::string>());
365 
366  auto result = options.parse(ac, av);
367 
368  if (result.count("help"))
369  {
370  std::cout << options.help() << "\n";
371  exit(EXIT_SUCCESS);
372  }
373 
374 
375  backboneDir = GetPathArgument(result, "backbone-path", ExpectFile::True, OptionalArg::False);
376 
377  comparisonFiles = GetPathArgument(result["comparison-files"].as<std::vector<std::string>>(), OptionalArg::True);
378 
379  detectorDir = GetPathArgument(result, "detector-path", ExpectFile::True, OptionalArg::False);
380 
381  imageDir = GetPathArgument(result, "image-path", ExpectFile::True, OptionalArg::True);
382 
383  dynamicBackendPath = GetPathArgument(result, "dynamic-backends-path", ExpectFile::False, OptionalArg::True);
384 
385  prefBackendsBackbone = GetBackendIDs(result["preferred-backends-backbone"].as<std::vector<std::string>>());
386  LogBackendsInfo(prefBackendsBackbone, "Backbone");
387  prefBackendsDetector = GetBackendIDs(result["preferred-backends-detector"].as<std::vector<std::string>>());
388  LogBackendsInfo(prefBackendsDetector, "detector");
389 
390  dumpToDot = result["model-to-dot"].as<bool>() ? DumpToDot::True : DumpToDot::False;
391  }
392 
393  /// Takes a vector of backend strings and returns a vector of backendIDs
394  std::vector<BackendId> GetBackendIDs(const std::vector<std::string>& backendStrings)
395  {
396  std::vector<BackendId> backendIDs;
397  for (const auto& b : backendStrings)
398  {
399  backendIDs.push_back(BackendId(b));
400  }
401  return backendIDs;
402  }
403 
404  /// Verifies if the program argument with the name argName contains a valid file path.
405  /// Returns the valid file path string if given argument is associated a valid file path.
406  /// Otherwise throws an exception.
407  std::string GetPathArgument(cxxopts::ParseResult& result,
408  std::string&& argName,
409  ExpectFile expectFile,
410  OptionalArg isOptionalArg)
411  {
412  if (result.count(argName))
413  {
414  std::string path = result[argName].as<std::string>();
415  if (!ValidateFilePath(path, expectFile))
416  {
417  std::stringstream ss;
418  ss << "Argument given to" << argName << "is not a valid file path";
419  throw cxxopts::option_syntax_exception(ss.str().c_str());
420  }
421  return path;
422  }
423  else
424  {
425  if (isOptionalArg == OptionalArg::True)
426  {
427  return "";
428  }
429 
430  throw cxxopts::missing_argument_exception(argName);
431  }
432  }
433 
434  /// Assigns vector of strings to struct member variable
435  std::vector<std::string> GetPathArgument(const std::vector<std::string>& pathStrings, OptionalArg isOptional)
436  {
437  if (pathStrings.size() < 5){
438  if (isOptional == OptionalArg::True)
439  {
440  return std::vector<std::string>();
441  }
442  throw cxxopts::option_syntax_exception("Comparison files requires 5 file paths.");
443  }
444 
445  std::vector<std::string> filePaths;
446  for (auto& path : pathStrings)
447  {
448  filePaths.push_back(path);
449  if (!ValidateFilePath(filePaths.back(), ExpectFile::True))
450  {
451  throw cxxopts::option_syntax_exception("Argument given to Comparison Files is not a valid file path");
452  }
453  }
454  return filePaths;
455  }
456 
457  /// Log info about assigned backends
458  void LogBackendsInfo(std::vector<BackendId>& backends, std::string&& modelName)
459  {
460  std::string info;
461  info = "Preferred backends for " + modelName + " set to [ ";
462  for (auto const &backend : backends)
463  {
464  info = info + std::string(backend) + " ";
465  }
466  ARMNN_LOG(info) << info << "]";
467  }
468 
469  // Member variables
470  std::string backboneDir;
471  std::vector<std::string> comparisonFiles;
472  std::string detectorDir;
473  std::string imageDir;
474  std::string dynamicBackendPath;
475 
476  std::vector<BackendId> prefBackendsBackbone;
477  std::vector<BackendId> prefBackendsDetector;
478 
479  cxxopts::Options options;
480 
481  DumpToDot dumpToDot;
482 };
483 
484 int main(int argc, char* argv[])
485 {
486  // Configure logging
487  SetAllLoggingSinks(true, true, true);
488  SetLogFilter(LogSeverity::Trace);
489 
490  // Check and get given program arguments
491  ParseArgs progArgs = ParseArgs(argc, argv);
492 
493  // Create runtime
494  IRuntime::CreationOptions runtimeOptions; // default
495 
496  if (!progArgs.dynamicBackendPath.empty())
497  {
498  std::cout << "Loading backends from" << progArgs.dynamicBackendPath << "\n";
499  runtimeOptions.m_DynamicBackendsPath = progArgs.dynamicBackendPath;
500  }
501 
502  auto runtime = IRuntime::Create(runtimeOptions);
503  if (!runtime)
504  {
505  ARMNN_LOG(fatal) << "Could not create runtime.";
506  return -1;
507  }
508 
509  // Create TfLite Parsers
511  auto parser = ITfLiteParser::Create(parserOptions);
512 
513  // Load backbone model
514  ARMNN_LOG(info) << "Loading backbone...";
515  NetworkId backboneId;
516  const DumpToDot dumpToDot = progArgs.dumpToDot;
517  CHECK_OK(LoadModel(progArgs.backboneDir.c_str(),
518  *parser,
519  *runtime,
520  backboneId,
521  progArgs.prefBackendsBackbone,
523  dumpToDot));
524  auto inputId = parser->GetNetworkInputBindingInfo(0, "inputs");
525  auto bbOut0Id = parser->GetNetworkOutputBindingInfo(0, "input_to_detector_1");
526  auto bbOut1Id = parser->GetNetworkOutputBindingInfo(0, "input_to_detector_2");
527  auto bbOut2Id = parser->GetNetworkOutputBindingInfo(0, "input_to_detector_3");
528  auto backboneProfile = runtime->GetProfiler(backboneId);
529  backboneProfile->EnableProfiling(true);
530 
531 
532  // Load detector model
533  ARMNN_LOG(info) << "Loading detector...";
534  NetworkId detectorId;
535  CHECK_OK(LoadModel(progArgs.detectorDir.c_str(),
536  *parser,
537  *runtime,
538  detectorId,
539  progArgs.prefBackendsDetector,
541  dumpToDot));
542  auto detectIn0Id = parser->GetNetworkInputBindingInfo(0, "input_to_detector_1");
543  auto detectIn1Id = parser->GetNetworkInputBindingInfo(0, "input_to_detector_2");
544  auto detectIn2Id = parser->GetNetworkInputBindingInfo(0, "input_to_detector_3");
545  auto outputBoxesId = parser->GetNetworkOutputBindingInfo(0, "output_boxes");
546  auto detectorProfile = runtime->GetProfiler(detectorId);
547 
548  // Load input from file
549  ARMNN_LOG(info) << "Loading test image...";
550  auto image = LoadImage(progArgs.imageDir.c_str());
551  if (image.empty())
552  {
553  return LOAD_IMAGE_ERROR;
554  }
555 
556  // Allocate the intermediate tensors
557  std::vector<float> intermediateMem0(bbOut0Id.second.GetNumElements());
558  std::vector<float> intermediateMem1(bbOut1Id.second.GetNumElements());
559  std::vector<float> intermediateMem2(bbOut2Id.second.GetNumElements());
560  std::vector<float> intermediateMem3(outputBoxesId.second.GetNumElements());
561 
562  // Setup inputs and outputs
563  using BindingInfos = std::vector<armnn::BindingPointInfo>;
564  using FloatTensors = std::vector<std::reference_wrapper<std::vector<float>>>;
565 
566  InputTensors bbInputTensors = MakeInputTensors(BindingInfos{ inputId },
567  FloatTensors{ image });
568  OutputTensors bbOutputTensors = MakeOutputTensors(BindingInfos{ bbOut0Id, bbOut1Id, bbOut2Id },
569  FloatTensors{ intermediateMem0,
570  intermediateMem1,
571  intermediateMem2 });
572  InputTensors detectInputTensors = MakeInputTensors(BindingInfos{ detectIn0Id,
573  detectIn1Id,
574  detectIn2Id } ,
575  FloatTensors{ intermediateMem0,
576  intermediateMem1,
577  intermediateMem2 });
578  OutputTensors detectOutputTensors = MakeOutputTensors(BindingInfos{ outputBoxesId },
579  FloatTensors{ intermediateMem3 });
580 
581  static const int numIterations=2;
582  using DurationUS = std::chrono::duration<double, std::micro>;
583  std::vector<DurationUS> nmsDurations(0);
584  std::vector<yolov3::Detection> filtered_boxes;
585  nmsDurations.reserve(numIterations);
586  for (int i=0; i < numIterations; i++)
587  {
588  // Execute backbone
589  ARMNN_LOG(info) << "Running backbone...";
590  runtime->EnqueueWorkload(backboneId, bbInputTensors, bbOutputTensors);
591 
592  // Execute detector
593  ARMNN_LOG(info) << "Running detector...";
594  runtime->EnqueueWorkload(detectorId, detectInputTensors, detectOutputTensors);
595 
596  // Execute NMS
597  ARMNN_LOG(info) << "Running nms...";
598  using clock = std::chrono::steady_clock;
599  auto nmsStartTime = clock::now();
600  yolov3::NMSConfig config;
601  config.num_boxes = 127800;
602  config.num_classes = 80;
603  config.confidence_threshold = 0.9f;
604  config.iou_threshold = 0.5f;
605  filtered_boxes = yolov3::nms(config, intermediateMem3);
606  auto nmsEndTime = clock::now();
607 
608  // Enable the profiling after the warm-up run
609  if (i>0)
610  {
611  print_detection(std::cout, filtered_boxes);
612 
613  const auto nmsDuration = DurationUS(nmsStartTime - nmsEndTime);
614  nmsDurations.push_back(nmsDuration);
615  }
616  backboneProfile->EnableProfiling(true);
617  detectorProfile->EnableProfiling(true);
618  }
619  // Log timings to file
620  std::ofstream backboneProfileStream("backbone.json");
621  backboneProfile->Print(backboneProfileStream);
622  backboneProfileStream.close();
623 
624  std::ofstream detectorProfileStream("detector.json");
625  detectorProfile->Print(detectorProfileStream);
626  detectorProfileStream.close();
627 
628  // Manually construct the json output
629  std::ofstream nmsProfileStream("nms.json");
630  nmsProfileStream << "{" << "\n";
631  nmsProfileStream << R"( "NmsTimings": {)" << "\n";
632  nmsProfileStream << R"( "raw": [)" << "\n";
633  bool isFirst = true;
634  for (auto duration : nmsDurations)
635  {
636  if (!isFirst)
637  {
638  nmsProfileStream << ",\n";
639  }
640 
641  nmsProfileStream << " " << duration.count();
642  isFirst = false;
643  }
644  nmsProfileStream << "\n";
645  nmsProfileStream << R"( "units": "us")" << "\n";
646  nmsProfileStream << " ]" << "\n";
647  nmsProfileStream << " }" << "\n";
648  nmsProfileStream << "}" << "\n";
649  nmsProfileStream.close();
650 
651  if (progArgs.comparisonFiles.size() > 0)
652  {
653  CheckAccuracy(&intermediateMem0,
654  &intermediateMem1,
655  &intermediateMem2,
656  &intermediateMem3,
657  filtered_boxes,
658  progArgs.comparisonFiles);
659  }
660 
661  ARMNN_LOG(info) << "Run completed";
662  return 0;
663 }
void CheckAccuracy(std::vector< float > *toDetector0, std::vector< float > *toDetector1, std::vector< float > *toDetector2, std::vector< float > *detectorOutput, const std::vector< yolov3::Detection > &nmsOut, const std::vector< std::string > &filePaths)
void SetAllLoggingSinks(bool standardOut, bool debugOut, bool coloured)
Definition: Logging.cpp:191
int LoadModel(const char *filename, ITfLiteParser &parser, IRuntime &runtime, NetworkId &networkId, const std::vector< BackendId > &backendPreferences, ImportMemory enableImport, DumpToDot dumpToDot)
#define S_BOOL(name)
armnn::InputTensors MakeInputTensors(const std::vector< armnn::BindingPointInfo > &inputBindings, const std::vector< std::reference_wrapper< TContainer >> &inputDataContainers)
int main(int argc, char *argv[])
#define ARMNN_LOG(severity)
Definition: Logging.hpp:205
std::vector< std::pair< LayerBindingId, class ConstTensor > > InputTensors
Definition: Tensor.hpp:392
std::vector< armnn::BackendId > GetBackendIDs(const std::vector< std::string > &backendStringsVec)
Takes a vector of backend strings and returns a vector of backendIDs.
Copyright (c) 2021 ARM Limited and Contributors.
unsigned int num_boxes
Number of detected boxes.
Definition: NMS.hpp:15
static ITfLiteParserPtr Create(const armnn::Optional< TfLiteParserOptions > &options=armnn::EmptyOptional())
A tensor defined by a TensorInfo (shape and data type) and a mutable backing store.
Definition: Tensor.hpp:319
std::vector< float > LoadImage(const char *filename)
void SetLogFilter(LogSeverity level)
Definition: Logging.cpp:73
IOptimizedNetworkPtr Optimize(const INetwork &network, const std::vector< BackendId > &backendPreferences, const IDeviceSpec &deviceSpec, const OptimizerOptions &options=OptimizerOptions(), Optional< std::vector< std::string > &> messages=EmptyOptional())
Create an optimized version of the network.
Definition: Network.cpp:1864
void print_detection(std::ostream &os, const std::vector< Detection > &detections)
Print identified yolo detections.
Definition: NMS.cpp:96
#define CHECK_OK(v)
int NetworkId
Definition: IRuntime.hpp:27
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:327
std::vector< std::pair< LayerBindingId, class Tensor > > OutputTensors
Definition: Tensor.hpp:393
Status
enumeration
Definition: Types.hpp:42
ArmNN performs an optimization on each model/network before it gets loaded for execution.
Definition: INetwork.hpp:127
float iou_threshold
Inclusion threshold for Intersection-Over-Union.
Definition: NMS.hpp:17
std::string m_DynamicBackendsPath
Setting this value will override the paths set by the DYNAMIC_BACKEND_PATHS compiler directive Only a...
Definition: IRuntime.hpp:98
std::pair< armnn::LayerBindingId, armnn::TensorInfo > BindingPointInfo
Definition: Tensor.hpp:274
Base class for all ArmNN exceptions so that users can filter to just those.
Definition: Exceptions.hpp:46
std::vector< Detection > nms(const NMSConfig &config, const std::vector< float > &detected_boxes)
Perform Non-Maxima Supression on a list of given detections.
Definition: NMS.cpp:113
mapbox::util::variant< std::vector< float >, std::vector< int >, std::vector< unsigned char >, std::vector< int8_t > > TContainer
Definition: TContainer.hpp:18
MemorySource
Define the Memory Source to reduce copies.
Definition: Types.hpp:230
armnn::OutputTensors MakeOutputTensors(const std::vector< armnn::BindingPointInfo > &outputBindings, const std::vector< std::reference_wrapper< TContainer >> &outputDataContainers)
Non Maxima Suprresion configuration meta-data.
Definition: NMS.hpp:13
float confidence_threshold
Inclusion confidence threshold for a box.
Definition: NMS.hpp:16
bool compare_detection(const yolov3::Detection &detection, const std::vector< float > &expected)
Compare a detection object with a vector of float values.
Definition: NMS.cpp:84
bool ValidateFilePath(std::string &file, ExpectFile expectFile)
unsigned int num_classes
Number of classes in the detected boxes.
Definition: NMS.hpp:14