summaryrefslogtreecommitdiff
path: root/python/openvino/runtime/common/demo_utils/src/images_capture.cpp
diff options
context:
space:
mode:
authorEric Dao <eric@erickhangdao.com>2025-03-10 17:54:31 -0400
committerEric Dao <eric@erickhangdao.com>2025-03-10 17:54:31 -0400
commitab224e2e6ba65f5a369ec392f99cd8845ad06c98 (patch)
treea1e757e9341863ed52b8ad4c5a1c45933aab9da4 /python/openvino/runtime/common/demo_utils/src/images_capture.cpp
parent40da1752f2c8639186b72f6838aa415e854d0b1d (diff)
downloadthesis-master.tar.gz
thesis-master.tar.bz2
thesis-master.zip
completed thesisHEADmaster
Diffstat (limited to 'python/openvino/runtime/common/demo_utils/src/images_capture.cpp')
-rw-r--r--python/openvino/runtime/common/demo_utils/src/images_capture.cpp327
1 files changed, 327 insertions, 0 deletions
diff --git a/python/openvino/runtime/common/demo_utils/src/images_capture.cpp b/python/openvino/runtime/common/demo_utils/src/images_capture.cpp
new file mode 100644
index 0000000..febcdd7
--- /dev/null
+++ b/python/openvino/runtime/common/demo_utils/src/images_capture.cpp
@@ -0,0 +1,327 @@
+// Copyright (C) 2020-2022 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);
+}