Initial setup for CLion

This commit is contained in:
2026-03-28 16:54:11 +11:00
parent 239cc02591
commit 7b4134133c
1136 changed files with 811916 additions and 0 deletions

View File

@@ -0,0 +1,187 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "utils/args_helper.hpp"
#include "utils/slog.hpp"
#ifdef _WIN32
#include "w_dirent.hpp"
#else
#include <dirent.h>
#endif
//#include <gflags/gflags.h>
#include <sys/stat.h>
#include <map>
#include <algorithm>
#include <iterator>
#include <cctype>
#include <sstream>
void readInputFilesArguments(std::vector<std::string>& files, const std::string& arg) {
struct stat sb;
if (stat(arg.c_str(), &sb) != 0) {
if (arg.compare(0, 5, "rtsp:") != 0) {
slog::warn << "File " << arg << " cannot be opened!" << slog::endl;
return;
}
}
if (S_ISDIR(sb.st_mode)) {
DIR *dp;
dp = opendir(arg.c_str());
if (dp == nullptr) {
slog::warn << "Directory " << arg << " cannot be opened!" << slog::endl;
return;
}
struct dirent *ep;
while (nullptr != (ep = readdir(dp))) {
std::string fileName = ep->d_name;
if (fileName == "." || fileName == "..") continue;
files.push_back(arg + "/" + ep->d_name);
}
closedir(dp);
} else {
files.push_back(arg);
}
}
//void parseInputFilesArguments(std::vector<std::string>& files) {
// std::vector<std::string> args = gflags::GetArgvs();
// bool readArguments = false;
// for (size_t i = 0; i < args.size(); i++) {
// if (args.at(i) == "-i" || args.at(i) == "--i") {
// readArguments = true;
// continue;
// }
// if (!readArguments) {
// continue;
// }
// if (args.at(i).c_str()[0] == '-') {
// break;
// }
// readInputFilesArguments(files, args.at(i));
// }
//}
std::vector<std::string> split(const std::string& s, char delim) {
std::vector<std::string> result;
std::stringstream ss(s);
std::string item;
while (getline(ss, item, delim)) {
result.push_back(item);
}
return result;
}
void split(const std::string& s, char delim, std::vector<float> &out) {
std::stringstream ss(s);
std::string item;
while (getline(ss, item, delim)) {
try {
out.push_back(std::stof(item));
} catch (...) {
std::cerr<<"cannot split the string: \"" + s + "\" onto floats";
}
}
}
template <class It>
static std::string merge_impl(It begin, It end, const char* delim) {
std::stringstream ss;
std::copy(begin, end, std::ostream_iterator<std::string>(ss, delim));
std::string result = ss.str();
if (!result.empty()) {
result.resize(result.size() - strlen(delim));
}
return result;
}
std::string merge(std::initializer_list<std::string> list, const char* delim) {
return merge_impl(list.begin(), list.end(), delim);
}
std::string merge(const std::vector<std::string> &list, const char *delim) {
return merge_impl(list.begin(), list.end(), delim);
}
std::vector<std::string> parseDevices(const std::string& device_string) {
const std::string::size_type colon_position = device_string.find(":");
if (colon_position != std::string::npos) {
std::string device_type = device_string.substr(0, colon_position);
if (device_type == "HETERO" || device_type == "MULTI") {
std::string comma_separated_devices = device_string.substr(colon_position + 1);
std::vector<std::string> devices = split(comma_separated_devices, ',');
for (auto& device : devices)
device = device.substr(0, device.find("("));
return devices;
}
}
return {device_string};
}
// Format: <device1>:<value1>,<device2>:<value2> or just <value>
std::map<std::string, int32_t> parseValuePerDevice(const std::set<std::string>& devices,
const std::string& values_string) {
auto values_string_upper = values_string;
std::transform(values_string_upper.begin(),
values_string_upper.end(),
values_string_upper.begin(),
[](unsigned char c){ return std::toupper(c); });
std::map<std::string, int32_t> result;
auto device_value_strings = split(values_string_upper, ',');
for (auto& device_value_string : device_value_strings) {
auto device_value_vec = split(device_value_string, ':');
if (device_value_vec.size() == 2) {
auto it = std::find(devices.begin(), devices.end(), device_value_vec.at(0));
if (it != devices.end()) {
result[device_value_vec.at(0)] = std::stoi(device_value_vec.at(1));
}
} else if (device_value_vec.size() == 1) {
uint32_t value = std::stoi(device_value_vec.at(0));
for (const auto& device : devices) {
result[device] = value;
}
} else if (device_value_vec.size() != 0) {
std::cerr<<"Unknown string format: " << values_string;
return {};
}
}
return result;
}
cv::Size stringToSize(const std::string& str) {
std::vector<std::string> strings = split(str, 'x');
if (strings.size() != 2) {
return cv::Size(0, 0);
}
return {std::stoi(strings[0]), std::stoi(strings[1])};
}
std::map<std::string, ov::Layout> parseLayoutString(const std::string& layout_string) {
// Parse parameter string like "input0:NCHW,input1:NC" or "NCHW" (applied to all
// inputs)
std::map<std::string, ov::Layout> layouts;
std::string searchStr = (layout_string.find_last_of(':') == std::string::npos && !layout_string.empty() ?
":" : "") + layout_string;
auto colonPos = searchStr.find_last_of(':');
while (colonPos != std::string::npos) {
auto startPos = searchStr.find_last_of(',');
auto inputName = searchStr.substr(startPos + 1, colonPos - startPos - 1);
auto inputLayout = searchStr.substr(colonPos + 1);
layouts[inputName] = ov::Layout(inputLayout);
searchStr = searchStr.substr(0, startPos + 1);
if (searchStr.empty() || searchStr.back() != ',') {
break;
}
searchStr.pop_back();
colonPos = searchStr.find_last_of(':');
}
if (!searchStr.empty()) {
return layouts;
}
return layouts;
}

View File

@@ -0,0 +1,65 @@
/*
// Copyright (C) 2023-2024 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
#include <fstream>
#include <map>
#include "utils/common.hpp"
std::vector<unsigned> loadClassIndices(const std::string &groundtruth_filepath,
const std::vector<std::string> &imageNames)
{
std::vector<unsigned> classIndices;
if (groundtruth_filepath.empty()) {
classIndices.resize(imageNames.size(), 0);
} else {
std::map<std::string, unsigned> classIndicesMap;
std::ifstream inputGtFile(groundtruth_filepath);
if (!inputGtFile.is_open()) {
throw std::runtime_error("Can't open the ground truth file: " + groundtruth_filepath);
}
std::string line;
while (std::getline(inputGtFile, line)) {
size_t separatorIdx = line.find(' ');
if (separatorIdx == std::string::npos) {
throw std::runtime_error("The ground truth file has incorrect format.");
}
std::string imagePath = line.substr(0, separatorIdx);
size_t imagePathEndIdx = imagePath.rfind('/');
unsigned classIndex = static_cast<unsigned>(std::stoul(line.substr(separatorIdx + 1)));
if ((imagePathEndIdx != 1 || imagePath[0] != '.') && imagePathEndIdx != std::string::npos) {
throw std::runtime_error("The ground truth file has incorrect format.");
}
// std::map type for classIndicesMap guarantees to sort out images by name.
// The same logic is applied in openImagesCapture() for DirReader source type,
// which produces data for sorted pictures.
// To be coherent in detection of ground truth for pictures we have to
// use the same sorting approach for a source and ground truth data
// If you're going to copy paste this code, remember that pictures need to be sorted
classIndicesMap.insert({imagePath.substr(imagePathEndIdx + 1), classIndex});
}
for (size_t i = 0; i < imageNames.size(); i++) {
auto imageSearchResult = classIndicesMap.find(imageNames[i]);
if (imageSearchResult != classIndicesMap.end()) {
classIndices.push_back(imageSearchResult->second);
} else {
throw std::runtime_error("No class specified for image " + imageNames[i]);
}
}
}
return classIndices;
}

View File

@@ -0,0 +1,100 @@
/*
// Copyright (C) 2020-2024 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
#include "utils/config_factory.h"
#include <set>
#include <string>
#include <utility>
#include <vector>
#include <openvino/runtime/intel_gpu/properties.hpp>
#include "utils/args_helper.hpp"
std::set<std::string> ModelConfig::getDevices() {
if (devices.empty()) {
for (const std::string& device : parseDevices(deviceName)) {
devices.insert(device);
}
}
return devices;
}
ModelConfig ConfigFactory::getUserConfig(const std::string& flags_d,
uint32_t flags_nireq,
const std::string& flags_nstreams,
uint32_t flags_nthreads) {
auto config = getCommonConfig(flags_d, flags_nireq);
std::map<std::string, int> deviceNstreams = parseValuePerDevice(config.getDevices(), flags_nstreams);
for (const auto& device : config.getDevices()) {
if (device == "CPU") { // CPU supports a few special performance-oriented keys
// limit threading for CPU portion of inference
if (flags_nthreads != 0)
config.compiledModelConfig.emplace(ov::inference_num_threads.name(), flags_nthreads);
//config.compiledModelConfig.emplace(ov::affinity.name(), ov::Affinity::NONE);
//config.compiledModelConfig.emplace(ov::hint::enable_cpu_pinning); // Do not know how to use it
ov::streams::Num nstreams =
deviceNstreams.count(device) > 0 ? ov::streams::Num(deviceNstreams[device]) : ov::streams::AUTO;
config.compiledModelConfig.emplace(ov::streams::num.name(), nstreams);
} else if (device == "GPU") {
ov::streams::Num nstreams =
deviceNstreams.count(device) > 0 ? ov::streams::Num(deviceNstreams[device]) : ov::streams::AUTO;
config.compiledModelConfig.emplace(ov::streams::num.name(), nstreams);
if (flags_d.find("MULTI") != std::string::npos &&
config.getDevices().find("CPU") != config.getDevices().end()) {
// multi-device execution with the CPU + GPU performs best with GPU throttling hint,
// which releases another CPU thread (that is otherwise used by the GPU driver for active polling)
config.compiledModelConfig.emplace(ov::intel_gpu::hint::queue_throttle.name(),
ov::intel_gpu::hint::ThrottleLevel(1));
}
}
}
return config;
}
ModelConfig ConfigFactory::getMinLatencyConfig(const std::string& flags_d, uint32_t flags_nireq) {
auto config = getCommonConfig(flags_d, flags_nireq);
for (const auto& device : config.getDevices()) {
if (device == "CPU") { // CPU supports a few special performance-oriented keys
config.compiledModelConfig.emplace(ov::streams::num.name(), 1);
} else if (device == "GPU") {
config.compiledModelConfig.emplace(ov::streams::num.name(), 1);
}
}
return config;
}
ModelConfig ConfigFactory::getCommonConfig(const std::string& flags_d, uint32_t flags_nireq) {
ModelConfig config;
if (!flags_d.empty()) {
config.deviceName = flags_d;
}
config.maxAsyncRequests = flags_nireq;
return config;
}
std::map<std::string, std::string> ModelConfig::getLegacyConfig() const {
std::map<std::string, std::string> config;
for (const auto& item : compiledModelConfig) {
config[item.first] = item.second.as<std::string>();
}
return config;
}

View File

@@ -0,0 +1,55 @@
/*
// Copyright (C) 2021-2024 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
#include "utils/image_utils.h"
cv::Mat resizeImageExt(const cv::Mat& mat, int width, int height, RESIZE_MODE resizeMode,
cv::InterpolationFlags interpolationMode, cv::Rect* roi, cv::Scalar BorderConstant) {
if (width == mat.cols && height == mat.rows) {
return mat;
}
cv::Mat dst;
switch (resizeMode) {
case RESIZE_FILL:
{
cv::resize(mat, dst, cv::Size(width, height), interpolationMode);
if (roi) {
*roi = cv::Rect(0, 0, width, height);
}
break;
}
case RESIZE_KEEP_ASPECT:
case RESIZE_KEEP_ASPECT_LETTERBOX:
{
double scale = std::min(static_cast<double>(width) / mat.cols, static_cast<double>(height) / mat.rows);
cv::Mat resizedImage;
cv::resize(mat, resizedImage, cv::Size(0, 0), scale, scale, interpolationMode);
int dx = resizeMode == RESIZE_KEEP_ASPECT ? 0 : (width - resizedImage.cols) / 2;
int dy = resizeMode == RESIZE_KEEP_ASPECT ? 0 : (height - resizedImage.rows) / 2;
cv::copyMakeBorder(resizedImage, dst, dy, height - resizedImage.rows - dy,
dx, width - resizedImage.cols - dx, cv::BORDER_CONSTANT, BorderConstant);
if (roi) {
*roi = cv::Rect(dx, dy, resizedImage.cols, resizedImage.rows);
}
break;
}
}
return dst;
}

View File

@@ -0,0 +1,326 @@
// Copyright (C) 2020-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "utils/images_capture.h"
#include <string.h>
#ifdef _WIN32
# include "w_dirent.hpp"
#else
# include <dirent.h> // for closedir, dirent, opendir, readdir, DIR
#endif
#include <algorithm>
#include <chrono>
#include <fstream>
#include <memory>
#include <stdexcept>
#include <string>
#include <vector>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/videoio.hpp>
class InvalidInput : public std::runtime_error {
public:
explicit InvalidInput(const std::string& message) noexcept : std::runtime_error(message) {}
};
class OpenError : public std::runtime_error {
public:
explicit OpenError(const std::string& message) noexcept : std::runtime_error(message) {}
};
class ImreadWrapper : public ImagesCapture {
cv::Mat img;
bool canRead;
public:
ImreadWrapper(const std::string& input, bool loop) : ImagesCapture{loop}, canRead{true} {
auto startTime = std::chrono::steady_clock::now();
std::ifstream file(input.c_str());
if (!file.good())
throw InvalidInput("Can't find the image by " + input);
img = cv::imread(input);
if (!img.data)
throw OpenError("Can't open the image from " + input);
else
readerMetrics.update(startTime);
}
double fps() const override {
return 1.0;
}
std::string getType() const override {
return "IMAGE";
}
cv::Mat read() override {
if (loop)
return img.clone();
if (canRead) {
canRead = false;
return img.clone();
}
return cv::Mat{};
}
};
class DirReader : public ImagesCapture {
std::vector<std::string> names;
size_t fileId;
size_t nextImgId;
const size_t initialImageId;
const size_t readLengthLimit;
const std::string input;
public:
DirReader(const std::string& input, bool loop, size_t initialImageId, size_t readLengthLimit)
: ImagesCapture{loop},
fileId{0},
nextImgId{0},
initialImageId{initialImageId},
readLengthLimit{readLengthLimit},
input{input} {
DIR* dir = opendir(input.c_str());
if (!dir)
throw InvalidInput("Can't find the dir by " + input);
while (struct dirent* ent = readdir(dir))
if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, ".."))
names.emplace_back(ent->d_name);
closedir(dir);
if (names.empty())
throw OpenError("The dir " + input + " is empty");
sort(names.begin(), names.end());
size_t readImgs = 0;
while (fileId < names.size()) {
cv::Mat img = cv::imread(input + '/' + names[fileId]);
if (img.data) {
++readImgs;
if (readImgs - 1 >= initialImageId)
return;
}
++fileId;
}
throw OpenError("Can't read the first image from " + input);
}
double fps() const override {
return 1.0;
}
std::string getType() const override {
return "DIR";
}
cv::Mat read() override {
auto startTime = std::chrono::steady_clock::now();
while (fileId < names.size() && nextImgId < readLengthLimit) {
cv::Mat img = cv::imread(input + '/' + names[fileId]);
++fileId;
if (img.data) {
++nextImgId;
readerMetrics.update(startTime);
return img;
}
}
if (loop) {
fileId = 0;
size_t readImgs = 0;
while (fileId < names.size()) {
cv::Mat img = cv::imread(input + '/' + names[fileId]);
++fileId;
if (img.data) {
++readImgs;
if (readImgs - 1 >= initialImageId) {
nextImgId = 1;
readerMetrics.update(startTime);
return img;
}
}
}
}
return cv::Mat{};
}
};
class VideoCapWrapper : public ImagesCapture {
cv::VideoCapture cap;
bool first_read;
const read_type type;
size_t nextImgId;
const double initialImageId;
size_t readLengthLimit;
public:
VideoCapWrapper(const std::string& input, bool loop, read_type type, size_t initialImageId, size_t readLengthLimit)
: ImagesCapture{loop},
first_read{true},
type{type},
nextImgId{0},
initialImageId{static_cast<double>(initialImageId)} {
if (0 == readLengthLimit) {
throw std::runtime_error("readLengthLimit must be positive");
}
if (cap.open(input)) {
this->readLengthLimit = readLengthLimit;
if (!cap.set(cv::CAP_PROP_POS_FRAMES, this->initialImageId))
throw OpenError("Can't set the frame to begin with");
return;
}
throw InvalidInput("Can't open the video from " + input);
}
double fps() const override {
return cap.get(cv::CAP_PROP_FPS);
}
std::string getType() const override {
return "VIDEO";
}
cv::Mat read() override {
auto startTime = std::chrono::steady_clock::now();
if (nextImgId >= readLengthLimit) {
if (loop && cap.set(cv::CAP_PROP_POS_FRAMES, initialImageId)) {
nextImgId = 1;
cv::Mat img;
cap.read(img);
if (type == read_type::safe) {
img = img.clone();
}
readerMetrics.update(startTime);
return img;
}
return cv::Mat{};
}
cv::Mat img;
bool success = cap.read(img);
if (!success && first_read) {
throw std::runtime_error("The first image can't be read");
}
first_read = false;
if (!success && loop && cap.set(cv::CAP_PROP_POS_FRAMES, initialImageId)) {
nextImgId = 1;
cap.read(img);
} else {
++nextImgId;
}
if (type == read_type::safe) {
img = img.clone();
}
readerMetrics.update(startTime);
return img;
}
};
class CameraCapWrapper : public ImagesCapture {
cv::VideoCapture cap;
const read_type type;
size_t nextImgId;
size_t readLengthLimit;
public:
CameraCapWrapper(const std::string& input,
bool loop,
read_type type,
size_t readLengthLimit,
cv::Size cameraResolution)
: ImagesCapture{loop},
type{type},
nextImgId{0} {
if (0 == readLengthLimit) {
throw std::runtime_error("readLengthLimit must be positive");
}
try {
if (cap.open(std::stoi(input))) {
this->readLengthLimit = loop ? std::numeric_limits<size_t>::max() : readLengthLimit;
cap.set(cv::CAP_PROP_BUFFERSIZE, 1);
cap.set(cv::CAP_PROP_FRAME_WIDTH, cameraResolution.width);
cap.set(cv::CAP_PROP_FRAME_HEIGHT, cameraResolution.height);
cap.set(cv::CAP_PROP_AUTOFOCUS, true);
cap.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));
return;
}
throw OpenError("Can't open the camera from " + input);
} catch (const std::invalid_argument&) {
throw InvalidInput("Can't find the camera " + input);
} catch (const std::out_of_range&) { throw InvalidInput("Can't find the camera " + input); }
}
double fps() const override {
return cap.get(cv::CAP_PROP_FPS) > 0 ? cap.get(cv::CAP_PROP_FPS) : 30;
}
std::string getType() const override {
return "CAMERA";
}
cv::Mat read() override {
auto startTime = std::chrono::steady_clock::now();
if (nextImgId >= readLengthLimit) {
return cv::Mat{};
}
cv::Mat img;
if (!cap.read(img)) {
throw std::runtime_error("The image can't be captured from the camera");
}
if (type == read_type::safe) {
img = img.clone();
}
++nextImgId;
readerMetrics.update(startTime);
return img;
}
};
std::unique_ptr<ImagesCapture> openImagesCapture(const std::string& input,
bool loop,
read_type type,
size_t initialImageId,
size_t readLengthLimit,
cv::Size cameraResolution) {
if (readLengthLimit == 0)
throw std::runtime_error{"Read length limit must be positive"};
std::vector<std::string> invalidInputs, openErrors;
try {
return std::unique_ptr<ImagesCapture>(new ImreadWrapper{input, loop});
} catch (const InvalidInput& e) { invalidInputs.push_back(e.what()); } catch (const OpenError& e) {
openErrors.push_back(e.what());
}
try {
return std::unique_ptr<ImagesCapture>(new DirReader{input, loop, initialImageId, readLengthLimit});
} catch (const InvalidInput& e) { invalidInputs.push_back(e.what()); } catch (const OpenError& e) {
openErrors.push_back(e.what());
}
try {
return std::unique_ptr<ImagesCapture>(new VideoCapWrapper{input, loop, type, initialImageId, readLengthLimit});
} catch (const InvalidInput& e) { invalidInputs.push_back(e.what()); } catch (const OpenError& e) {
openErrors.push_back(e.what());
}
try {
return std::unique_ptr<ImagesCapture>(
new CameraCapWrapper{input, loop, type, readLengthLimit, cameraResolution});
} catch (const InvalidInput& e) { invalidInputs.push_back(e.what()); } catch (const OpenError& e) {
openErrors.push_back(e.what());
}
std::vector<std::string> errorMessages = openErrors.empty() ? invalidInputs : openErrors;
std::string errorsInfo;
for (const auto& message : errorMessages) {
errorsInfo.append(message + "\n");
}
throw std::runtime_error(errorsInfo);
}

View File

@@ -0,0 +1,169 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <algorithm>
#include <limits>
#include <vector>
#include <utils/kuhn_munkres.hpp>
KuhnMunkres::KuhnMunkres(bool greedy) : n_(), greedy_(greedy) {}
std::vector<size_t> KuhnMunkres::Solve(const cv::Mat& dissimilarity_matrix) {
CV_Assert(dissimilarity_matrix.type() == CV_32F);
double min_val;
cv::minMaxLoc(dissimilarity_matrix, &min_val);
n_ = std::max(dissimilarity_matrix.rows, dissimilarity_matrix.cols);
dm_ = cv::Mat(n_, n_, CV_32F, cv::Scalar(0));
marked_ = cv::Mat(n_, n_, CV_8S, cv::Scalar(0));
points_ = std::vector<cv::Point>(n_ * 2);
dissimilarity_matrix.copyTo(dm_(
cv::Rect(0, 0, dissimilarity_matrix.cols, dissimilarity_matrix.rows)));
is_row_visited_ = std::vector<int>(n_, 0);
is_col_visited_ = std::vector<int>(n_, 0);
Run();
std::vector<size_t> results(dissimilarity_matrix.rows, -1);
for (int i = 0; i < dissimilarity_matrix.rows; i++) {
const auto ptr = marked_.ptr<char>(i);
for (int j = 0; j < dissimilarity_matrix.cols; j++) {
if (ptr[j] == kStar) {
results[i] = (size_t)j;
}
}
}
return results;
}
void KuhnMunkres::TrySimpleCase() {
auto is_row_visited = std::vector<int>(n_, 0);
auto is_col_visited = std::vector<int>(n_, 0);
for (int row = 0; row < n_; row++) {
auto ptr = dm_.ptr<float>(row);
auto marked_ptr = marked_.ptr<char>(row);
auto min_val = *std::min_element(ptr, ptr + n_);
for (int col = 0; col < n_; col++) {
ptr[col] -= min_val;
if (ptr[col] == 0 && !is_col_visited[col] && !is_row_visited[row]) {
marked_ptr[col] = kStar;
is_col_visited[col] = 1;
is_row_visited[row] = 1;
}
}
}
}
bool KuhnMunkres::CheckIfOptimumIsFound() {
int count = 0;
for (int i = 0; i < n_; i++) {
const auto marked_ptr = marked_.ptr<char>(i);
for (int j = 0; j < n_; j++) {
if (marked_ptr[j] == kStar) {
is_col_visited_[j] = 1;
count++;
}
}
}
return count >= n_;
}
cv::Point KuhnMunkres::FindUncoveredMinValPos() {
auto min_val = std::numeric_limits<float>::max();
cv::Point min_val_pos(-1, -1);
for (int i = 0; i < n_; i++) {
if (!is_row_visited_[i]) {
auto dm_ptr = dm_.ptr<float>(i);
for (int j = 0; j < n_; j++) {
if (!is_col_visited_[j] && dm_ptr[j] < min_val) {
min_val = dm_ptr[j];
min_val_pos = cv::Point(j, i);
}
}
}
}
return min_val_pos;
}
void KuhnMunkres::UpdateDissimilarityMatrix(float val) {
for (int i = 0; i < n_; i++) {
auto dm_ptr = dm_.ptr<float>(i);
for (int j = 0; j < n_; j++) {
if (is_row_visited_[i]) dm_ptr[j] += val;
if (!is_col_visited_[j]) dm_ptr[j] -= val;
}
}
}
int KuhnMunkres::FindInRow(int row, int what) {
for (int j = 0; j < n_; j++) {
if (marked_.at<char>(row, j) == what) {
return j;
}
}
return -1;
}
int KuhnMunkres::FindInCol(int col, int what) {
for (int i = 0; i < n_; i++) {
if (marked_.at<char>(i, col) == what) {
return i;
}
}
return -1;
}
void KuhnMunkres::Run() {
TrySimpleCase();
if (greedy_)
return;
while (!CheckIfOptimumIsFound()) {
while (true) {
auto point = FindUncoveredMinValPos();
auto min_val = dm_.at<float>(point.y, point.x);
if (min_val > 0) {
UpdateDissimilarityMatrix(min_val);
} else {
marked_.at<char>(point.y, point.x) = kPrime;
int col = FindInRow(point.y, kStar);
if (col >= 0) {
is_row_visited_[point.y] = 1;
is_col_visited_[col] = 0;
} else {
int count = 0;
points_[count] = point;
while (true) {
int row = FindInCol(points_[count].x, kStar);
if (row >= 0) {
count++;
points_[count] = cv::Point(points_[count - 1].x, row);
int col = FindInRow(points_[count].y, kPrime);
count++;
points_[count] = cv::Point(col, points_[count - 1].y);
} else {
break;
}
}
for (int i = 0; i < count + 1; i++) {
auto& mark = marked_.at<char>(points_[i].y, points_[i].x);
mark = mark == kStar ? 0 : kStar;
}
is_row_visited_ = std::vector<int>(n_, 0);
is_col_visited_ = std::vector<int>(n_, 0);
marked_.setTo(0, marked_ == kPrime);
break;
}
}
}
}
}

View File

@@ -0,0 +1,114 @@
// Copyright (C) 2020-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <limits>
#include "utils/performance_metrics.hpp"
#include "utils/slog.hpp"
// timeWindow defines the length of the timespan over which the 'current fps' value is calculated
PerformanceMetrics::PerformanceMetrics(Duration timeWindow)
: timeWindowSize(timeWindow)
, firstFrameProcessed(false)
{}
void PerformanceMetrics::update(TimePoint lastRequestStartTime,
const cv::Mat& frame,
cv::Point position,
int fontFace,
double fontScale,
cv::Scalar color,
int thickness,
MetricTypes metricType) {
update(lastRequestStartTime);
paintMetrics(frame, position, fontFace, fontScale, color, thickness, metricType);
}
void PerformanceMetrics::update(TimePoint lastRequestStartTime) {
TimePoint currentTime = Clock::now();
if (!firstFrameProcessed) {
lastUpdateTime = lastRequestStartTime;
firstFrameProcessed = true;
}
currentMovingStatistic.latency += currentTime - lastRequestStartTime;
currentMovingStatistic.period = currentTime - lastUpdateTime;
currentMovingStatistic.frameCount++;
if (currentTime - lastUpdateTime > timeWindowSize) {
lastMovingStatistic = currentMovingStatistic;
totalStatistic.combine(lastMovingStatistic);
currentMovingStatistic = Statistic();
lastUpdateTime = currentTime;
}
}
void PerformanceMetrics::paintMetrics(const cv::Mat& frame, cv::Point position, int fontFace,
double fontScale, cv::Scalar color, int thickness, MetricTypes metricType) const {
// Draw performance stats over frame
Metrics metrics = getLast();
std::ostringstream out;
if (!std::isnan(metrics.latency) &&
(metricType == PerformanceMetrics::MetricTypes::LATENCY || metricType == PerformanceMetrics::MetricTypes::ALL)) {
out << "Latency: " << std::fixed << std::setprecision(1) << metrics.latency << " ms";
putHighlightedText(frame, out.str(), position, fontFace, fontScale, color, thickness);
}
if (!std::isnan(metrics.fps) &&
(metricType == PerformanceMetrics::MetricTypes::FPS || metricType == PerformanceMetrics::MetricTypes::ALL)) {
out.str("");
out << "FPS: " << std::fixed << std::setprecision(1) << metrics.fps;
int offset = metricType == PerformanceMetrics::MetricTypes::ALL ? 30 : 0;
putHighlightedText(frame, out.str(), {position.x, position.y + offset}, fontFace, fontScale, color, thickness);
}
}
PerformanceMetrics::Metrics PerformanceMetrics::getLast() const {
Metrics metrics;
metrics.latency = lastMovingStatistic.frameCount != 0
? std::chrono::duration_cast<Ms>(lastMovingStatistic.latency).count()
/ lastMovingStatistic.frameCount
: std::numeric_limits<double>::signaling_NaN();
metrics.fps = lastMovingStatistic.period != Duration::zero()
? lastMovingStatistic.frameCount
/ std::chrono::duration_cast<Sec>(lastMovingStatistic.period).count()
: std::numeric_limits<double>::signaling_NaN();
return metrics;
}
PerformanceMetrics::Metrics PerformanceMetrics::getTotal() const {
Metrics metrics;
int frameCount = totalStatistic.frameCount + currentMovingStatistic.frameCount;
if (frameCount != 0) {
metrics.latency = std::chrono::duration_cast<Ms>(
totalStatistic.latency + currentMovingStatistic.latency).count() / frameCount;
metrics.fps = frameCount / std::chrono::duration_cast<Sec>(
totalStatistic.period + currentMovingStatistic.period).count();
} else {
metrics.latency = std::numeric_limits<double>::signaling_NaN();
metrics.fps = std::numeric_limits<double>::signaling_NaN();
}
return metrics;
}
void PerformanceMetrics::logTotal() const {
Metrics metrics = getTotal();
slog::info << "\tLatency: " << std::fixed << std::setprecision(1) << metrics.latency << " ms" << slog::endl;
slog::info << "\tFPS: " << metrics.fps << slog::endl;
}
void logLatencyPerStage(double readLat, double preprocLat, double inferLat, double postprocLat, double renderLat) {
slog::info << "\tDecoding:\t" << std::fixed << std::setprecision(1) <<
readLat << " ms" << slog::endl;
slog::info << "\tPreprocessing:\t" << preprocLat << " ms" << slog::endl;
slog::info << "\tInference:\t" << inferLat << " ms" << slog::endl;
slog::info << "\tPostprocessing:\t" << postprocLat << " ms" << slog::endl;
slog::info << "\tRendering:\t" << renderLat << " ms" << slog::endl;
}

View File

@@ -0,0 +1,180 @@
/*
// Copyright (C) 2021-2024 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
#include "utils/visualizer.hpp"
#include <ctype.h>
#include <stddef.h>
#include <memory>
#include <stdexcept>
#include <string>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <models/results.h>
#include <pipelines/metadata.h>
#include <utils/ocv_common.hpp>
Visualizer::Visualizer(const std::string& type) {
if (type == "sr")
winName = "Image Processing Demo - Super Resolution (press A for help)";
else if (type == "jr")
winName = "Image Processing Demo - JPEG Restoration (press A for help)";
}
cv::Size Visualizer::getSize() {
return resolution;
}
void Visualizer::handleKey(int key) {
key = std::tolower(key);
if (key == 'a') {
isHelpShown = !isHelpShown;
}
if (cv::getWindowProperty(winName, 0) < 0) {
mode = "result";
disableTrackbar();
}
if (key == 'o') {
mode = "orig";
addTrackbar();
}
if (key == 'v') {
mode = "diff";
addTrackbar();
}
if (key == 'r') {
mode = "result";
cv::destroyWindow(winName);
disableTrackbar();
}
}
cv::Mat Visualizer::renderResultData(ImageResult result, cv::Size& newResolution) {
if (!result.metaData) {
throw std::invalid_argument("Renderer: metadata is null");
}
// Input image is stored inside metadata, as we put it there during submission stage
inputImg = result.metaData->asRef<ImageMetaData>().img;
if (inputImg.empty()) {
throw std::invalid_argument("Renderer: image provided in metadata is empty");
}
if (!isResolutionSet) {
setResolution(newResolution);
}
cv::resize(result.resultImage, result.resultImage, resolution);
cv::resize(inputImg, inputImg, resolution);
if (inputImg.channels() != result.resultImage.channels()) {
cv::cvtColor(result.resultImage, resultImg, cv::COLOR_GRAY2BGR);
} else {
resultImg = result.resultImage;
}
/* changeDisplayImg();
displayImg=resultImg.clone();*/
return resultImg;
}
void Visualizer::show(cv::Mat img) {
if (img.empty()) {
changeDisplayImg();
img = displayImg;
}
if (isHelpShown) {
int pad = 10;
int margin = 60;
int baseline = 0;
int lineH = cv::getTextSize(helpMessage[0], cv::FONT_HERSHEY_COMPLEX_SMALL, 0.75, 1, &baseline).height + pad;
for (size_t i = 0; i < 4; ++i) {
putHighlightedText(img,
helpMessage[i],
cv::Point(pad, margin + baseline + (i + 1) * lineH),
cv::FONT_HERSHEY_COMPLEX,
0.65,
cv::Scalar(255, 0, 0),
2);
}
}
cv::imshow(winName, img);
}
void Visualizer::changeDisplayImg() {
displayImg = resultImg.clone();
if (mode == "orig") {
inputImg(cv::Rect(0, 0, slider, inputImg.rows)).copyTo(displayImg(cv::Rect(0, 0, slider, resultImg.rows)));
markImage(displayImg, {"O", "R"}, static_cast<float>(slider) / resolution.width);
drawSweepLine(displayImg);
} else if (mode == "result") {
markImage(displayImg, {"R", ""}, 1);
} else if (mode == "diff") {
cv::Mat diffImg;
cv::absdiff(inputImg, resultImg, diffImg);
double min, max;
cv::minMaxLoc(diffImg, &min, &max);
double scale = 255.0 / (max - min);
diffImg = (diffImg - min) * scale;
diffImg(cv::Rect(0, 0, slider, resultImg.rows)).copyTo(displayImg(cv::Rect(0, 0, slider, displayImg.rows)));
markImage(displayImg, {"D", "R"}, static_cast<float>(slider) / resolution.width);
drawSweepLine(displayImg);
}
}
void Visualizer::markImage(cv::Mat& image, const std::pair<std::string, std::string>& marks, float alpha) {
int pad = 25;
std::pair<float, float> positions(static_cast<float>(image.cols) * alpha / 2.0f,
static_cast<float>(image.cols) * (1 + alpha) / 2.0f);
putHighlightedText(image,
marks.first,
cv::Point(static_cast<int>(positions.first) - pad, 25),
cv::FONT_HERSHEY_COMPLEX,
1,
cv::Scalar(0, 0, 255),
2);
putHighlightedText(image,
marks.second,
cv::Point(static_cast<int>(positions.second), 25),
cv::FONT_HERSHEY_COMPLEX,
1,
cv::Scalar(0, 0, 255),
2);
}
void Visualizer::drawSweepLine(cv::Mat& image) {
cv::line(image, cv::Point(slider, 0), cv::Point(slider, image.rows), cv::Scalar(0, 255, 0), 2);
}
void Visualizer::setResolution(cv::Size& newResolution) {
resolution = newResolution;
isResolutionSet = true;
}
void Visualizer::addTrackbar() {
if (!isTrackbarShown) {
cv::createTrackbar(trackbarName, winName, &slider, resolution.width);
cv::setTrackbarMin(trackbarName, winName, 1);
isTrackbarShown = true;
}
}
void Visualizer::disableTrackbar() {
isTrackbarShown = false;
}

View File

@@ -0,0 +1,114 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#if defined(_WIN32)
#ifndef NOMINMAX
# define NOMINMAX
#endif
#include <WinSock2.h>
#include <Windows.h>
#include <stdlib.h>
#else
#include <unistd.h>
#include <cstdlib>
#include <string.h>
#endif
#include <string>
#include <sys/stat.h>
#if defined(WIN32)
// Copied from linux libc sys/stat.h:
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
struct dirent {
char *d_name;
explicit dirent(const wchar_t *wsFilePath) {
size_t i;
auto slen = wcslen(wsFilePath);
d_name = static_cast<char*>(malloc(slen + 1));
wcstombs_s(&i, d_name, slen + 1, wsFilePath, slen);
}
~dirent() {
free(d_name);
}
};
class DIR {
WIN32_FIND_DATAA FindFileData;
HANDLE hFind;
dirent *next;
static inline bool endsWith(const std::string &src, const char *with) {
int wl = static_cast<int>(strlen(with));
int so = static_cast<int>(src.length()) - wl;
if (so < 0) return false;
return 0 == strncmp(with, &src[so], wl);
}
public:
explicit DIR(const char *dirPath) : next(nullptr) {
std::string ws = dirPath;
if (endsWith(ws, "\\"))
ws += "*";
else
ws += "\\*";
hFind = FindFirstFileA(ws.c_str(), &FindFileData);
FindFileData.dwReserved0 = hFind != INVALID_HANDLE_VALUE;
}
~DIR() {
if (!next) delete next;
FindClose(hFind);
}
bool isValid() const {
return (hFind != INVALID_HANDLE_VALUE && FindFileData.dwReserved0);
}
dirent* nextEnt() {
if (next != nullptr) delete next;
next = nullptr;
if (!FindFileData.dwReserved0) return nullptr;
wchar_t wbuf[4096];
size_t outSize;
mbstowcs_s(&outSize, wbuf, 4094, FindFileData.cFileName, 4094);
next = new dirent(wbuf);
FindFileData.dwReserved0 = FindNextFileA(hFind, &FindFileData);
return next;
}
};
static DIR *opendir(const char* dirPath) {
auto dp = new DIR(dirPath);
if (!dp->isValid()) {
delete dp;
return nullptr;
}
return dp;
}
static struct dirent *readdir(DIR *dp) {
return dp->nextEnt();
}
static void closedir(DIR *dp) {
delete dp;
}