1*89c4ff92SAndroid Build Coastguard Worker //
2*89c4ff92SAndroid Build Coastguard Worker // Copyright © 2020 Arm Ltd and Contributors. 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 "ImageUtils.hpp"
7*89c4ff92SAndroid Build Coastguard Worker #include "BoundingBox.hpp"
8*89c4ff92SAndroid Build Coastguard Worker #include "Types.hpp"
9*89c4ff92SAndroid Build Coastguard Worker
10*89c4ff92SAndroid Build Coastguard Worker #include <armnn/Logging.hpp>
11*89c4ff92SAndroid Build Coastguard Worker
GetScalarColorCode(std::tuple<int,int,int> color)12*89c4ff92SAndroid Build Coastguard Worker static cv::Scalar GetScalarColorCode(std::tuple<int, int, int> color)
13*89c4ff92SAndroid Build Coastguard Worker {
14*89c4ff92SAndroid Build Coastguard Worker return cv::Scalar(std::get<0>(color), std::get<1>(color), std::get<2>(color));
15*89c4ff92SAndroid Build Coastguard Worker }
16*89c4ff92SAndroid Build Coastguard Worker
AddInferenceOutputToFrame(od::DetectedObjects & decodedResults,cv::Mat & inputFrame,std::vector<std::tuple<std::string,common::BBoxColor>> & labels)17*89c4ff92SAndroid Build Coastguard Worker void AddInferenceOutputToFrame(od::DetectedObjects& decodedResults, cv::Mat& inputFrame,
18*89c4ff92SAndroid Build Coastguard Worker std::vector<std::tuple<std::string, common::BBoxColor>>& labels)
19*89c4ff92SAndroid Build Coastguard Worker {
20*89c4ff92SAndroid Build Coastguard Worker for(const od::DetectedObject& object : decodedResults)
21*89c4ff92SAndroid Build Coastguard Worker {
22*89c4ff92SAndroid Build Coastguard Worker int confidence = static_cast<int>(object.GetScore() * 100);
23*89c4ff92SAndroid Build Coastguard Worker int baseline = 0;
24*89c4ff92SAndroid Build Coastguard Worker std::string textStr;
25*89c4ff92SAndroid Build Coastguard Worker std::tuple<int, int, int> colorCode(255, 0, 0); //red
26*89c4ff92SAndroid Build Coastguard Worker
27*89c4ff92SAndroid Build Coastguard Worker if (labels.size() > object.GetId())
28*89c4ff92SAndroid Build Coastguard Worker {
29*89c4ff92SAndroid Build Coastguard Worker auto label = labels[object.GetId()];
30*89c4ff92SAndroid Build Coastguard Worker textStr = std::get<0>(label) + " - " + std::to_string(confidence) + "%";
31*89c4ff92SAndroid Build Coastguard Worker colorCode = std::get<1>(label).colorCode;
32*89c4ff92SAndroid Build Coastguard Worker }
33*89c4ff92SAndroid Build Coastguard Worker else
34*89c4ff92SAndroid Build Coastguard Worker {
35*89c4ff92SAndroid Build Coastguard Worker textStr = std::to_string(object.GetId()) + " - " + std::to_string(confidence) + "%";
36*89c4ff92SAndroid Build Coastguard Worker }
37*89c4ff92SAndroid Build Coastguard Worker
38*89c4ff92SAndroid Build Coastguard Worker cv::Size textSize = getTextSize(textStr, cv::FONT_HERSHEY_DUPLEX, 1.0, 1, &baseline);
39*89c4ff92SAndroid Build Coastguard Worker
40*89c4ff92SAndroid Build Coastguard Worker const od::BoundingBox& bbox = object.GetBoundingBox();
41*89c4ff92SAndroid Build Coastguard Worker
42*89c4ff92SAndroid Build Coastguard Worker if (bbox.GetX() + bbox.GetWidth() > inputFrame.cols)
43*89c4ff92SAndroid Build Coastguard Worker {
44*89c4ff92SAndroid Build Coastguard Worker cv::Rect r(bbox.GetX(), bbox.GetY(), inputFrame.cols - bbox.GetX(), bbox.GetHeight());
45*89c4ff92SAndroid Build Coastguard Worker
46*89c4ff92SAndroid Build Coastguard Worker cv::rectangle(inputFrame, r, GetScalarColorCode(colorCode), 2, 8, 0);
47*89c4ff92SAndroid Build Coastguard Worker }
48*89c4ff92SAndroid Build Coastguard Worker else if (bbox.GetY() + bbox.GetHeight() > inputFrame.rows)
49*89c4ff92SAndroid Build Coastguard Worker {
50*89c4ff92SAndroid Build Coastguard Worker cv::Rect r(bbox.GetX(), bbox.GetY(), bbox.GetWidth(), inputFrame.rows - bbox.GetY());
51*89c4ff92SAndroid Build Coastguard Worker
52*89c4ff92SAndroid Build Coastguard Worker cv::rectangle(inputFrame, r, GetScalarColorCode(colorCode), 2, 8, 0);
53*89c4ff92SAndroid Build Coastguard Worker }
54*89c4ff92SAndroid Build Coastguard Worker else
55*89c4ff92SAndroid Build Coastguard Worker {
56*89c4ff92SAndroid Build Coastguard Worker cv::Rect r(bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight());
57*89c4ff92SAndroid Build Coastguard Worker
58*89c4ff92SAndroid Build Coastguard Worker cv::rectangle(inputFrame, r, GetScalarColorCode(colorCode), 2, 8, 0);
59*89c4ff92SAndroid Build Coastguard Worker }
60*89c4ff92SAndroid Build Coastguard Worker
61*89c4ff92SAndroid Build Coastguard Worker int textBoxY = std::max(0 ,bbox.GetY() - textSize.height);
62*89c4ff92SAndroid Build Coastguard Worker
63*89c4ff92SAndroid Build Coastguard Worker cv::Rect text(bbox.GetX(), textBoxY, textSize.width, textSize.height);
64*89c4ff92SAndroid Build Coastguard Worker
65*89c4ff92SAndroid Build Coastguard Worker cv::rectangle(inputFrame, text, GetScalarColorCode(colorCode), -1);
66*89c4ff92SAndroid Build Coastguard Worker
67*89c4ff92SAndroid Build Coastguard Worker cv::Scalar color;
68*89c4ff92SAndroid Build Coastguard Worker
69*89c4ff92SAndroid Build Coastguard Worker if(std::get<0>(colorCode) + std::get<1>(colorCode) + std::get<2>(colorCode) > 127)
70*89c4ff92SAndroid Build Coastguard Worker {
71*89c4ff92SAndroid Build Coastguard Worker color = cv::Scalar::all(0);
72*89c4ff92SAndroid Build Coastguard Worker }
73*89c4ff92SAndroid Build Coastguard Worker else
74*89c4ff92SAndroid Build Coastguard Worker {
75*89c4ff92SAndroid Build Coastguard Worker color = cv::Scalar::all(255);
76*89c4ff92SAndroid Build Coastguard Worker }
77*89c4ff92SAndroid Build Coastguard Worker
78*89c4ff92SAndroid Build Coastguard Worker cv::putText(inputFrame,
79*89c4ff92SAndroid Build Coastguard Worker textStr ,
80*89c4ff92SAndroid Build Coastguard Worker cv::Point(bbox.GetX(), textBoxY + textSize.height -(textSize.height)/3),
81*89c4ff92SAndroid Build Coastguard Worker cv::FONT_HERSHEY_DUPLEX,
82*89c4ff92SAndroid Build Coastguard Worker 0.5,
83*89c4ff92SAndroid Build Coastguard Worker color,
84*89c4ff92SAndroid Build Coastguard Worker 1);
85*89c4ff92SAndroid Build Coastguard Worker }
86*89c4ff92SAndroid Build Coastguard Worker }
87*89c4ff92SAndroid Build Coastguard Worker
88*89c4ff92SAndroid Build Coastguard Worker
ResizeFrame(const cv::Mat & frame,cv::Mat & dest,const common::Size & aspectRatio)89*89c4ff92SAndroid Build Coastguard Worker void ResizeFrame(const cv::Mat& frame, cv::Mat& dest, const common::Size& aspectRatio)
90*89c4ff92SAndroid Build Coastguard Worker {
91*89c4ff92SAndroid Build Coastguard Worker if(&dest != &frame)
92*89c4ff92SAndroid Build Coastguard Worker {
93*89c4ff92SAndroid Build Coastguard Worker double longEdgeInput = std::max(frame.rows, frame.cols);
94*89c4ff92SAndroid Build Coastguard Worker double longEdgeOutput = std::max(aspectRatio.m_Width, aspectRatio.m_Height);
95*89c4ff92SAndroid Build Coastguard Worker const double resizeFactor = longEdgeOutput/longEdgeInput;
96*89c4ff92SAndroid Build Coastguard Worker cv::resize(frame, dest, cv::Size(0, 0), resizeFactor, resizeFactor, DefaultResizeFlag);
97*89c4ff92SAndroid Build Coastguard Worker }
98*89c4ff92SAndroid Build Coastguard Worker else
99*89c4ff92SAndroid Build Coastguard Worker {
100*89c4ff92SAndroid Build Coastguard Worker const std::string warningMessage{"Resize was not performed because resized frame references the source frame."};
101*89c4ff92SAndroid Build Coastguard Worker ARMNN_LOG(warning) << warningMessage;
102*89c4ff92SAndroid Build Coastguard Worker }
103*89c4ff92SAndroid Build Coastguard Worker }
104*89c4ff92SAndroid Build Coastguard Worker
105*89c4ff92SAndroid Build Coastguard Worker /** Pad a frame with zeros (add rows and columns to the end) */
PadFrame(const cv::Mat & src,cv::Mat & dest,const int bottom,const int right)106*89c4ff92SAndroid Build Coastguard Worker void PadFrame(const cv::Mat& src, cv::Mat& dest, const int bottom, const int right)
107*89c4ff92SAndroid Build Coastguard Worker {
108*89c4ff92SAndroid Build Coastguard Worker if(&dest != &src)
109*89c4ff92SAndroid Build Coastguard Worker {
110*89c4ff92SAndroid Build Coastguard Worker cv::copyMakeBorder(src, dest, 0, bottom, 0, right, cv::BORDER_CONSTANT);
111*89c4ff92SAndroid Build Coastguard Worker }
112*89c4ff92SAndroid Build Coastguard Worker else
113*89c4ff92SAndroid Build Coastguard Worker {
114*89c4ff92SAndroid Build Coastguard Worker const std::string warningMessage
115*89c4ff92SAndroid Build Coastguard Worker {
116*89c4ff92SAndroid Build Coastguard Worker "Pad was not performed because destination frame references the source frame."
117*89c4ff92SAndroid Build Coastguard Worker };
118*89c4ff92SAndroid Build Coastguard Worker ARMNN_LOG(warning) << warningMessage;
119*89c4ff92SAndroid Build Coastguard Worker }
120*89c4ff92SAndroid Build Coastguard Worker }
121*89c4ff92SAndroid Build Coastguard Worker
ResizeWithPad(const cv::Mat & frame,cv::Mat & dest,cv::Mat & cache,const common::Size & destSize)122*89c4ff92SAndroid Build Coastguard Worker void ResizeWithPad(const cv::Mat& frame, cv::Mat& dest, cv::Mat& cache, const common::Size& destSize)
123*89c4ff92SAndroid Build Coastguard Worker {
124*89c4ff92SAndroid Build Coastguard Worker ResizeFrame(frame, cache, destSize);
125*89c4ff92SAndroid Build Coastguard Worker PadFrame(cache, dest,destSize.m_Height - cache.rows,destSize.m_Width - cache.cols);
126*89c4ff92SAndroid Build Coastguard Worker }
127