Initial setup for CLion
This commit is contained in:
187
engines/OpenVINOEngine/src/utils/args_helper.cpp
Normal file
187
engines/OpenVINOEngine/src/utils/args_helper.cpp
Normal 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;
|
||||
}
|
||||
65
engines/OpenVINOEngine/src/utils/common.cpp
Normal file
65
engines/OpenVINOEngine/src/utils/common.cpp
Normal 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;
|
||||
}
|
||||
100
engines/OpenVINOEngine/src/utils/config_factory.cpp
Normal file
100
engines/OpenVINOEngine/src/utils/config_factory.cpp
Normal 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;
|
||||
}
|
||||
55
engines/OpenVINOEngine/src/utils/image_utils.cpp
Normal file
55
engines/OpenVINOEngine/src/utils/image_utils.cpp
Normal 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;
|
||||
}
|
||||
326
engines/OpenVINOEngine/src/utils/images_capture.cpp
Normal file
326
engines/OpenVINOEngine/src/utils/images_capture.cpp
Normal 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);
|
||||
}
|
||||
169
engines/OpenVINOEngine/src/utils/kuhn_munkres.cpp
Normal file
169
engines/OpenVINOEngine/src/utils/kuhn_munkres.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
114
engines/OpenVINOEngine/src/utils/performance_metrics.cpp
Normal file
114
engines/OpenVINOEngine/src/utils/performance_metrics.cpp
Normal 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;
|
||||
}
|
||||
180
engines/OpenVINOEngine/src/utils/visualizer.cpp
Normal file
180
engines/OpenVINOEngine/src/utils/visualizer.cpp
Normal 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;
|
||||
}
|
||||
114
engines/OpenVINOEngine/src/utils/w_dirent.hpp
Normal file
114
engines/OpenVINOEngine/src/utils/w_dirent.hpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user