From 919c14ef132986aa1514b2070ce6d19b5579a6ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89anna=20=C3=93=20Cath=C3=A1in?= Date: Mon, 14 Sep 2020 17:36:49 +0100 Subject: MLECO-929 Add Object Detection sample application using the public ArmNN C++ API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I14aa1b4b726212cffbefd6687203f93f936fa872 Signed-off-by: Éanna Ó Catháin --- samples/ObjectDetection/src/ImageUtils.cpp | 126 +++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 samples/ObjectDetection/src/ImageUtils.cpp (limited to 'samples/ObjectDetection/src/ImageUtils.cpp') diff --git a/samples/ObjectDetection/src/ImageUtils.cpp b/samples/ObjectDetection/src/ImageUtils.cpp new file mode 100644 index 0000000000..9a3ed17b63 --- /dev/null +++ b/samples/ObjectDetection/src/ImageUtils.cpp @@ -0,0 +1,126 @@ +// +// Copyright © 2020 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "ImageUtils.hpp" +#include "BoundingBox.hpp" +#include "Types.hpp" + +#include + +static cv::Scalar GetScalarColorCode(std::tuple color) +{ + return cv::Scalar(std::get<0>(color), std::get<1>(color), std::get<2>(color)); +} + +void AddInferenceOutputToFrame(od::DetectedObjects& decodedResults, cv::Mat& inputFrame, + std::vector>& labels) +{ + for(const od::DetectedObject& object : decodedResults) + { + int confidence = static_cast(object.GetScore() * 100); + int baseline = 0; + std::string textStr; + std::tuple colorCode(255, 0, 0); //red + + if (labels.size() > object.GetId()) + { + auto label = labels[object.GetId()]; + textStr = std::get<0>(label) + " - " + std::to_string(confidence) + "%"; + colorCode = std::get<1>(label).colorCode; + } + else + { + textStr = std::to_string(object.GetId()) + " - " + std::to_string(confidence) + "%"; + } + + cv::Size textSize = getTextSize(textStr, cv::FONT_HERSHEY_DUPLEX, 1.0, 1, &baseline); + + const od::BoundingBox& bbox = object.GetBoundingBox(); + + if (bbox.GetX() + bbox.GetWidth() > inputFrame.cols) + { + cv::Rect r(bbox.GetX(), bbox.GetY(), inputFrame.cols - bbox.GetX(), bbox.GetHeight()); + + cv::rectangle(inputFrame, r, GetScalarColorCode(colorCode), 2, 8, 0); + } + else if (bbox.GetY() + bbox.GetHeight() > inputFrame.rows) + { + cv::Rect r(bbox.GetX(), bbox.GetY(), bbox.GetWidth(), inputFrame.rows - bbox.GetY()); + + cv::rectangle(inputFrame, r, GetScalarColorCode(colorCode), 2, 8, 0); + } + else + { + cv::Rect r(bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight()); + + cv::rectangle(inputFrame, r, GetScalarColorCode(colorCode), 2, 8, 0); + } + + int textBoxY = std::max(0 ,bbox.GetY() - textSize.height); + + cv::Rect text(bbox.GetX(), textBoxY, textSize.width, textSize.height); + + cv::rectangle(inputFrame, text, GetScalarColorCode(colorCode), -1); + + cv::Scalar color; + + if(std::get<0>(colorCode) + std::get<1>(colorCode) + std::get<2>(colorCode) > 127) + { + color = cv::Scalar::all(0); + } + else + { + color = cv::Scalar::all(255); + } + + cv::putText(inputFrame, + textStr , + cv::Point(bbox.GetX(), textBoxY + textSize.height -(textSize.height)/3), + cv::FONT_HERSHEY_DUPLEX, + 0.5, + color, + 1); + } +} + + +void ResizeFrame(const cv::Mat& frame, cv::Mat& dest, const od::Size& aspectRatio) +{ + if(&dest != &frame) + { + double longEdgeInput = std::max(frame.rows, frame.cols); + double longEdgeOutput = std::max(aspectRatio.m_Width, aspectRatio.m_Height); + const double resizeFactor = longEdgeOutput/longEdgeInput; + cv::resize(frame, dest, cv::Size(0, 0), resizeFactor, resizeFactor, DefaultResizeFlag); + } + else + { + const std::string warningMessage{"Resize was not performed because resized frame references the source frame."}; + ARMNN_LOG(warning) << warningMessage; + } +} + +/** Pad a frame with zeros (add rows and columns to the end) */ +void PadFrame(const cv::Mat& src, cv::Mat& dest, const int bottom, const int right) +{ + if(&dest != &src) + { + cv::copyMakeBorder(src, dest, 0, bottom, 0, right, cv::BORDER_CONSTANT); + } + else + { + const std::string warningMessage + { + "Pad was not performed because destination frame references the source frame." + }; + ARMNN_LOG(warning) << warningMessage; + } +} + +void ResizeWithPad(const cv::Mat& frame, cv::Mat& dest, cv::Mat& cache, const od::Size& destSize) +{ + ResizeFrame(frame, cache, destSize); + PadFrame(cache, dest,destSize.m_Height - cache.rows,destSize.m_Width - cache.cols); +} -- cgit v1.2.1