ArmNN
 20.05
MobileNetSsdDatabase.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #pragma once
7 
8 #include "InferenceTestImage.hpp"
10 
11 #include <QuantizeHelper.hpp>
12 
13 #include <armnn/TypesUtils.hpp>
14 
15 #include <boost/numeric/conversion/cast.hpp>
16 
17 #include <array>
18 #include <memory>
19 #include <string>
20 #include <vector>
21 
22 namespace
23 {
24 
25 struct MobileNetSsdTestCaseData
26 {
27  MobileNetSsdTestCaseData(
28  const std::vector<uint8_t>& inputData,
29  const std::vector<DetectedObject>& expectedDetectedObject,
30  const std::vector<std::vector<float>>& expectedOutput)
31  : m_InputData(inputData)
32  , m_ExpectedDetectedObject(expectedDetectedObject)
33  , m_ExpectedOutput(expectedOutput)
34  {}
35 
36  std::vector<uint8_t> m_InputData;
37  std::vector<DetectedObject> m_ExpectedDetectedObject;
38  std::vector<std::vector<float>> m_ExpectedOutput;
39 };
40 
41 class MobileNetSsdDatabase
42 {
43 public:
44  explicit MobileNetSsdDatabase(const std::string& imageDir, float scale, int offset);
45 
46  std::unique_ptr<MobileNetSsdTestCaseData> GetTestCaseData(unsigned int testCaseId);
47 
48 private:
49  std::string m_ImageDir;
50  float m_Scale;
51  int m_Offset;
52 };
53 
54 constexpr unsigned int k_MobileNetSsdImageWidth = 300u;
55 constexpr unsigned int k_MobileNetSsdImageHeight = k_MobileNetSsdImageWidth;
56 
57 // Test cases
58 const std::array<ObjectDetectionInput, 1> g_PerTestCaseInput =
59 {
60  ObjectDetectionInput
61  {
62  "Cat.jpg",
63  {
64  DetectedObject(16.0f, BoundingBox(0.216785252f, 0.079726994f, 0.927124202f, 0.939067304f), 0.79296875f)
65  }
66  }
67 };
68 
69 MobileNetSsdDatabase::MobileNetSsdDatabase(const std::string& imageDir, float scale, int offset)
70  : m_ImageDir(imageDir)
71  , m_Scale(scale)
72  , m_Offset(offset)
73 {}
74 
75 std::unique_ptr<MobileNetSsdTestCaseData> MobileNetSsdDatabase::GetTestCaseData(unsigned int testCaseId)
76 {
77  const unsigned int safeTestCaseId =
78  testCaseId % boost::numeric_cast<unsigned int>(g_PerTestCaseInput.size());
79  const ObjectDetectionInput& testCaseInput = g_PerTestCaseInput[safeTestCaseId];
80 
81  // Load test case input
82  const std::string imagePath = m_ImageDir + testCaseInput.first;
83  std::vector<uint8_t> imageData;
84  try
85  {
86  InferenceTestImage image(imagePath.c_str());
87 
88  // Resize image (if needed)
89  const unsigned int width = image.GetWidth();
90  const unsigned int height = image.GetHeight();
91  if (width != k_MobileNetSsdImageWidth || height != k_MobileNetSsdImageHeight)
92  {
93  image.Resize(k_MobileNetSsdImageWidth, k_MobileNetSsdImageHeight, CHECK_LOCATION());
94  }
95 
96  // Get image data as a vector of floats
97  std::vector<float> floatImageData = GetImageDataAsNormalizedFloats(ImageChannelLayout::Rgb, image);
98  imageData = armnnUtils::QuantizedVector<uint8_t>(floatImageData, m_Scale, m_Offset);
99  }
100  catch (const InferenceTestImageException& e)
101  {
102  ARMNN_LOG(fatal) << "Failed to load image for test case " << testCaseId << ". Error: " << e.what();
103  return nullptr;
104  }
105 
106  std::vector<float> numDetections = { static_cast<float>(testCaseInput.second.size()) };
107 
108  std::vector<float> detectionBoxes;
109  std::vector<float> detectionClasses;
110  std::vector<float> detectionScores;
111 
112  for (DetectedObject expectedObject : testCaseInput.second)
113  {
114  detectionBoxes.push_back(expectedObject.m_BoundingBox.m_YMin);
115  detectionBoxes.push_back(expectedObject.m_BoundingBox.m_XMin);
116  detectionBoxes.push_back(expectedObject.m_BoundingBox.m_YMax);
117  detectionBoxes.push_back(expectedObject.m_BoundingBox.m_XMax);
118 
119  detectionClasses.push_back(expectedObject.m_Class);
120 
121  detectionScores.push_back(expectedObject.m_Confidence);
122  }
123 
124  // Prepare test case expected output
125  std::vector<std::vector<float>> expectedOutputs;
126  expectedOutputs.reserve(4);
127  expectedOutputs.push_back(detectionBoxes);
128  expectedOutputs.push_back(detectionClasses);
129  expectedOutputs.push_back(detectionScores);
130  expectedOutputs.push_back(numDetections);
131 
132  return std::make_unique<MobileNetSsdTestCaseData>(imageData, testCaseInput.second, expectedOutputs);
133 }
134 
135 } // anonymous namespace
virtual const char * what() const noexcept override
Definition: Exceptions.cpp:32
#define ARMNN_LOG(severity)
Definition: Logging.hpp:163
unsigned int GetWidth() const
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
Definition: NumericCast.hpp:33
#define CHECK_LOCATION()
Definition: Exceptions.hpp:192
std::vector< float > GetImageDataAsNormalizedFloats(ImageChannelLayout layout, const InferenceTestImage &image)