11 #include <stb/stb_image.h> 23 using namespace armnn;
25 static const int OPEN_FILE_ERROR = -2;
26 static const int OPTIMIZE_NETWORK_ERROR = -3;
27 static const int LOAD_NETWORK_ERROR = -4;
28 static const int LOAD_IMAGE_ERROR = -5;
29 static const int GENERAL_ERROR = -100;
35 if (r_local != 0) { return r_local;} \ 37 catch(armnn::Exception e) \ 39 ARMNN_LOG(error) << "Oops: " << e.what(); \ 40 return GENERAL_ERROR; \ 46 template<
typename TContainer>
48 const std::vector<TContainer>& inputDataContainers)
52 const size_t numInputs = inputBindings.size();
53 if (numInputs != inputDataContainers.size())
58 for (
size_t i = 0; i < numInputs; i++)
61 const TContainer& inputData = inputDataContainers[i];
64 inputTensors.push_back(std::make_pair(inputBinding.first, inputTensor));
70 template<
typename TContainer>
72 const std::vector<TContainer>& outputDataContainers)
76 const size_t numOutputs = outputBindings.size();
77 if (numOutputs != outputDataContainers.size())
82 for (
size_t i = 0; i < numOutputs; i++)
85 const TContainer& outputData = outputDataContainers[i];
87 armnn::Tensor outputTensor(outputBinding.second, const_cast<float*>(outputData.data()));
88 outputTensors.push_back(std::make_pair(outputBinding.first, outputTensor));
98 const std::vector<BackendId>& backendPreferences)
100 std::ifstream stream(filename, std::ios::in | std::ios::binary);
101 if (!stream.is_open())
104 return OPEN_FILE_ERROR;
107 std::vector<uint8_t> contents((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
119 return OPTIMIZE_NETWORK_ERROR;
124 std::string errorMessage;
126 Status status = runtime.
LoadNetwork(networkId, std::move(optimizedModel), errorMessage, modelProps);
127 if (status != Status::Success)
129 ARMNN_LOG(
fatal) <<
"Could not load " << filename <<
" model into runtime: " << errorMessage;
130 return LOAD_NETWORK_ERROR;
141 ~Memory() {stbi_image_free(m_Data);}
142 bool IsLoaded()
const {
return m_Data !=
nullptr;}
144 unsigned char* m_Data;
147 std::vector<float> image;
153 Memory mem = {stbi_load(filename, &width, &height, &channels, 3)};
156 ARMNN_LOG(
error) <<
"Could not load input image file: " << filename;
160 if (width != 1920 || height != 1080 || channels != 3)
162 ARMNN_LOG(
error) <<
"Input image has wong dimension: " << width <<
"x" << height <<
"x" << channels <<
". " 163 " Expected 1920x1080x3.";
167 image.resize(1920*1080*3);
170 for (
unsigned int idx=0; idx <= 1920*1080*3; idx++)
172 image[idx] =
static_cast<float>(mem.m_Data[idx]) /255.0f;
178 int main(
int argc,
char* argv[])
182 ARMNN_LOG(
error) <<
"Expected arguments: {PathToModels} {PathToData}";
184 std::string modelsPath(argv[1]);
185 std::string imagePath(argv[2]);
187 std::string backboneModelFile = modelsPath +
"yolov3_1080_1920_backbone_int8.tflite";
188 std::string detectorModelFile = modelsPath +
"yolov3_1080_1920_detector_fp32.tflite";
189 std::string imageFile = imagePath +
"1080_1920.jpg";
198 auto runtime = IRuntime::Create(runtimeOptions);
212 CHECK_OK(
LoadModel(backboneModelFile.c_str(), *parser, *runtime, backboneId, {
"GpuAcc",
"CpuRef"}));
213 auto inputId = parser->GetNetworkInputBindingInfo(0,
"inputs");
214 auto bbOut0Id = parser->GetNetworkOutputBindingInfo(0,
"input_to_detector_1");
215 auto bbOut1Id = parser->GetNetworkOutputBindingInfo(0,
"input_to_detector_2");
216 auto bbOut2Id = parser->GetNetworkOutputBindingInfo(0,
"input_to_detector_3");
217 auto backboneProfile = runtime->GetProfiler(backboneId);
218 backboneProfile->EnableProfiling(
true);
223 CHECK_OK(
LoadModel(detectorModelFile.c_str(), *parser, *runtime, detectorId, {
"CpuAcc",
"CpuRef"}));
224 auto detectIn0Id = parser->GetNetworkInputBindingInfo(0,
"input_to_detector_1");
225 auto detectIn1Id = parser->GetNetworkInputBindingInfo(0,
"input_to_detector_2");
226 auto detectIn2Id = parser->GetNetworkInputBindingInfo(0,
"input_to_detector_3");
227 auto outputBoxesId = parser->GetNetworkOutputBindingInfo(0,
"output_boxes");
228 auto detectorProfile = runtime->GetProfiler(detectorId);
232 auto image =
LoadImage(imageFile.c_str());
235 return LOAD_IMAGE_ERROR;
240 std::vector<float> intermediateMem0(bbOut0Id.second.GetNumElements());
241 std::vector<float> intermediateMem1(bbOut1Id.second.GetNumElements());
242 std::vector<float> intermediateMem2(bbOut2Id.second.GetNumElements());
243 std::vector<float> intermediateMem3(outputBoxesId.second.GetNumElements());
246 using BindingInfos = std::vector<armnn::BindingPointInfo>;
247 using FloatTensors = std::vector<std::vector<float>>;
250 FloatTensors{std::move(image)});
252 FloatTensors{intermediateMem0,
258 FloatTensors{intermediateMem0,
262 FloatTensors{intermediateMem3});
264 static const int numIterations=2;
265 using DurationUS = std::chrono::duration<double, std::micro>;
266 std::vector<DurationUS> nmsDurations(0);
267 nmsDurations.reserve(numIterations);
268 for (
int i=0; i < numIterations; i++)
272 runtime->EnqueueWorkload(backboneId, bbInputTensors, bbOutputTensors);
276 runtime->EnqueueWorkload(detectorId, detectInputTensors, detectOutputTensors);
280 using clock = std::chrono::steady_clock;
281 auto nmsStartTime = clock::now();
287 auto filtered_boxes =
yolov3::nms(config, intermediateMem3);
288 auto nmsEndTime = clock::now();
295 const auto nmsDuration = DurationUS(nmsStartTime - nmsEndTime);
296 nmsDurations.push_back(nmsDuration);
298 backboneProfile->EnableProfiling(
true);
299 detectorProfile->EnableProfiling(
true);
302 std::ofstream backboneProfileStream(
"backbone.json");
303 backboneProfile->Print(backboneProfileStream);
304 backboneProfileStream.close();
306 std::ofstream detectorProfileStream(
"detector.json");
307 detectorProfile->Print(detectorProfileStream);
308 detectorProfileStream.close();
311 std::ofstream nmsProfileStream(
"nms.json");
312 nmsProfileStream <<
"{" <<
"\n";
313 nmsProfileStream << R
"( "NmsTimings": {)" << "\n";
314 nmsProfileStream << R
"( "raw": [)" << "\n";
316 for (
auto duration : nmsDurations)
320 nmsProfileStream <<
",\n";
323 nmsProfileStream <<
" " << duration.count();
326 nmsProfileStream <<
"\n";
327 nmsProfileStream << R
"( "units": "us")" << "\n";
328 nmsProfileStream <<
" ]" <<
"\n";
329 nmsProfileStream <<
" }" <<
"\n";
330 nmsProfileStream <<
"}" <<
"\n";
331 nmsProfileStream.close();
void SetAllLoggingSinks(bool standardOut, bool debugOut, bool coloured)
int main(int argc, char *argv[])
#define ARMNN_LOG(severity)
std::vector< std::pair< LayerBindingId, class ConstTensor > > InputTensors
Copyright (c) 2020 ARM Limited.
unsigned int num_boxes
Number of detected boxes.
static ITfLiteParserPtr Create(const armnn::Optional< TfLiteParserOptions > &options=armnn::EmptyOptional())
armnn::OutputTensors MakeOutputTensors(const std::vector< armnn::BindingPointInfo > &outputBindings, const std::vector< TContainer > &outputDataContainers)
virtual const IDeviceSpec & GetDeviceSpec() const =0
A tensor defined by a TensorInfo (shape and data type) and a mutable backing store.
std::vector< float > LoadImage(const char *filename)
void SetLogFilter(LogSeverity level)
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.
void print_detection(std::ostream &os, const std::vector< Detection > &detections)
Print identified yolo detections.
virtual armnn::INetworkPtr CreateNetworkFromBinary(const std::vector< uint8_t > &binaryContent)=0
Create the network from a flatbuffers binary.
virtual Status LoadNetwork(NetworkId &networkIdOut, IOptimizedNetworkPtr network)=0
Loads a complete network into the IRuntime.
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
std::vector< std::pair< LayerBindingId, class Tensor > > OutputTensors
float iou_threshold
Inclusion threshold for Intersection-Over-Union.
boost::variant< std::vector< float >, std::vector< int >, std::vector< unsigned char > > TContainer
std::pair< armnn::LayerBindingId, armnn::TensorInfo > BindingPointInfo
Base class for all ArmNN exceptions so that users can filter to just those.
std::vector< Detection > nms(const NMSConfig &config, const std::vector< float > &detected_boxes)
Perform Non-Maxima Supression on a list of given detections.
Non Maxima Suprresion configuration meta-data.
float confidence_threshold
Inclusion confidence threshold for a box.
armnn::InputTensors MakeInputTensors(const std::vector< armnn::BindingPointInfo > &inputBindings, const std::vector< TContainer > &inputDataContainers)
int LoadModel(const char *filename, ITfLiteParser &parser, IRuntime &runtime, NetworkId &networkId, const std::vector< BackendId > &backendPreferences)
unsigned int num_classes
Number of classes in the detected boxes.