Refactor project structure

This commit is contained in:
2026-03-28 19:56:39 +11:00
parent 1d267378b2
commit 8a2e721058
511 changed files with 59 additions and 48 deletions

328
modules/ANSLPR/ANSLPR_OV.h Normal file
View File

@@ -0,0 +1,328 @@
#ifndef ANSLPROV_H
#define ANSLPROV_H
#pragma once
#include "ANSLPR.h"
#include <list>
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "openvino/openvino.hpp"
#include "openvino/runtime/intel_gpu/properties.hpp"
#include "utils/args_helper.hpp"
#include "utils/input_wrappers.hpp"
#include "utils/common.hpp"
#include "utils/ocv_common.hpp"
#include "utils/threads_common.hpp"
#include "utils/grid_mat.hpp"
#include "monitors/presenter.h"
namespace ANSCENTER
{
void tryPush(const std::weak_ptr<Worker>& worker, std::shared_ptr<Task>&& task);
struct BboxAndDescr {
enum class ObjectType {
NONE,
VEHICLE,
PLATE,
} objectType;
cv::Rect rect;
std::string descr;
};
class Detector {
public:
struct Result {
std::size_t label;
float confidence;
cv::Rect location;
};
static constexpr int maxProposalCount = 200;
static constexpr int objectSize = 7; // Output should have 7 as a last dimension"
Detector() = default;
Detector(ov::Core& core,
const std::string& deviceName,
const std::string& xmlPath,
const std::vector<float>& detectionTresholds,
const bool autoResize);
ov::InferRequest createInferRequest();
void setImage(ov::InferRequest& inferRequest, const cv::Mat& img);
std::list<Result> getResults(ov::InferRequest& inferRequest, cv::Size upscale, std::vector<std::string>& rawResults);
private:
bool m_autoResize;
std::vector<float> m_detectionTresholds;
std::string m_detectorInputName;
std::string m_detectorOutputName;
ov::CompiledModel m_compiled_model;
};
class VehicleAttributesClassifier {
public:
VehicleAttributesClassifier() = default;
VehicleAttributesClassifier(ov::Core& core,
const std::string& deviceName,
const std::string& xmlPath,
const bool autoResize);
ov::InferRequest createInferRequest();
void setImage(ov::InferRequest& inferRequest, const cv::Mat& img, const cv::Rect vehicleRect);
std::pair<std::string, std::string> getResults(ov::InferRequest& inferRequest);
private:
bool m_autoResize;
std::string m_attributesInputName;
std::string m_outputNameForColor;
std::string m_outputNameForType;
ov::CompiledModel m_compiled_model;
};
class Lpr {
public:
Lpr() = default;
Lpr(ov::Core& core,
const std::string& deviceName,
const std::string& xmlPath,
const bool autoResize);
ov::InferRequest createInferRequest();
void setImage(ov::InferRequest& inferRequest, const cv::Mat& img, const cv::Rect plateRect);
std::string getResults(ov::InferRequest& inferRequest);
private:
bool m_autoResize;
int m_maxSequenceSizePerPlate = 0;
std::string m_LprInputName;
std::string m_LprInputSeqName;
std::string m_LprOutputName;
ov::Layout m_modelLayout;
ov::CompiledModel m_compiled_model;
};
//Utilities
struct InferRequestsContainer {
InferRequestsContainer() = default;
InferRequestsContainer(const InferRequestsContainer&) = delete;
InferRequestsContainer& operator=(const InferRequestsContainer&) = delete;
void assign(const std::vector<ov::InferRequest>& inferRequests) {
actualInferRequests = inferRequests;
this->inferRequests.container.clear();
for (auto& ir : this->actualInferRequests) {
this->inferRequests.container.push_back(ir);
}
}
ConcurrentContainer<std::vector<std::reference_wrapper<ov::InferRequest>>> inferRequests;
std::vector<ov::InferRequest> actualInferRequests;
};
// stores all global data for tasks
struct Context {
Context(const std::vector<std::shared_ptr<InputChannel>>& inputChannels,
const Detector& detector,
const VehicleAttributesClassifier& vehicleAttributesClassifier,
const Lpr& lpr,
uint64_t lastFrameId,
uint64_t nireq,
bool isVideo,
std::size_t nclassifiersireq,
std::size_t nrecognizersireq) :
readersContext{ inputChannels, std::vector<int64_t>(inputChannels.size(), -1), std::vector<std::mutex>(inputChannels.size()) },
inferTasksContext{ detector },
detectionsProcessorsContext{ vehicleAttributesClassifier, lpr },
videoFramesContext{ std::vector<uint64_t>(inputChannels.size(), lastFrameId), std::vector<std::mutex>(inputChannels.size()) },
nireq{ nireq },
isVideo{ isVideo },
freeDetectionInfersCount{ 0 },
frameCounter{ 0 }
{
std::vector<ov::InferRequest> detectorInferRequests;
std::vector<ov::InferRequest> attributesInferRequests;
std::vector<ov::InferRequest> lprInferRequests;
detectorInferRequests.reserve(nireq);
attributesInferRequests.reserve(nclassifiersireq);
lprInferRequests.reserve(nrecognizersireq);
std::generate_n(std::back_inserter(detectorInferRequests), nireq, [&] {return inferTasksContext.detector.createInferRequest(); });
std::generate_n(std::back_inserter(attributesInferRequests), nclassifiersireq, [&] {return detectionsProcessorsContext.vehicleAttributesClassifier.createInferRequest(); });
std::generate_n(std::back_inserter(lprInferRequests), nrecognizersireq, [&] {return detectionsProcessorsContext.lpr.createInferRequest(); });
detectorsInfers.assign(detectorInferRequests);
attributesInfers.assign(attributesInferRequests);
platesInfers.assign(lprInferRequests);
}
struct {
std::vector<std::shared_ptr<InputChannel>> inputChannels;
std::vector<int64_t> lastCapturedFrameIds;
std::vector<std::mutex> lastCapturedFrameIdsMutexes;
std::weak_ptr<Worker> readersWorker;
} readersContext;
struct {
Detector detector;
std::weak_ptr<Worker> inferTasksWorker;
} inferTasksContext;
struct {
VehicleAttributesClassifier vehicleAttributesClassifier;
Lpr lpr;
std::weak_ptr<Worker> detectionsProcessorsWorker;
} detectionsProcessorsContext;
struct {
std::vector<uint64_t> lastframeIds;
std::vector<std::mutex> lastFrameIdsMutexes;
} videoFramesContext;
std::weak_ptr<Worker> resAggregatorsWorker;
std::mutex classifiersAggregatorPrintMutex;
uint64_t nireq;
bool isVideo;
std::atomic<std::vector<ov::InferRequest>::size_type> freeDetectionInfersCount;
std::atomic<uint32_t> frameCounter;
InferRequestsContainer detectorsInfers, attributesInfers, platesInfers;
PerformanceMetrics metrics;
std::list<BboxAndDescr> boxesAndDescrs;
};
// End of Context
class ReborningVideoFrame : public VideoFrame {
public:
ReborningVideoFrame(Context& context,
const unsigned sourceID,
const int64_t frameId,
const cv::Mat& frame = cv::Mat()) :
VideoFrame{ sourceID, frameId, frame },
context(context) {}
virtual ~ReborningVideoFrame();
Context& context;
};
// draws results on the frame
class ResAggregator : public Task {
public:
ResAggregator(const VideoFrame::Ptr& sharedVideoFrame,
std::list<BboxAndDescr>&& boxesAndDescrs) :
Task{ sharedVideoFrame, 4.0 },
boxesAndDescrs{ std::move(boxesAndDescrs) } {}
bool isReady() override {
return true;
}
void process() override;
private:
std::list<BboxAndDescr> boxesAndDescrs;
};
// waits for all classifiers and recognisers accumulating results
class ClassifiersAggregator {
public:
std::vector<std::string> rawDetections;
ConcurrentContainer<std::list<std::string>> rawAttributes;
ConcurrentContainer<std::list<std::string>> rawDecodedPlates;
explicit ClassifiersAggregator(const VideoFrame::Ptr& sharedVideoFrame) :
sharedVideoFrame{ sharedVideoFrame } {}
~ClassifiersAggregator() {
std::mutex& printMutex = static_cast<ReborningVideoFrame*>(sharedVideoFrame.get())->context.classifiersAggregatorPrintMutex;
printMutex.lock();
if (!rawDetections.empty()) {
slog::debug << "Frame #: " << sharedVideoFrame->frameId << slog::endl;
slog::debug << rawDetections;
// destructor assures that none uses the container
for (const std::string& rawAttribute : rawAttributes.container) {
slog::debug << rawAttribute << slog::endl;
}
for (const std::string& rawDecodedPlate : rawDecodedPlates.container) {
slog::debug << rawDecodedPlate << slog::endl;
}
}
printMutex.unlock();
tryPush(static_cast<ReborningVideoFrame*>(sharedVideoFrame.get())->context.resAggregatorsWorker,
std::make_shared<ResAggregator>(sharedVideoFrame, std::move(boxesAndDescrs)));
}
void push(BboxAndDescr&& bboxAndDescr) {
boxesAndDescrs.lockedPushBack(std::move(bboxAndDescr));
}
const VideoFrame::Ptr sharedVideoFrame;
private:
ConcurrentContainer<std::list<BboxAndDescr>> boxesAndDescrs;
};
// extracts detections from blob InferRequests and runs classifiers and recognisers
class DetectionsProcessor : public Task {
public:
DetectionsProcessor(VideoFrame::Ptr sharedVideoFrame, ov::InferRequest* inferRequest) :
Task{ sharedVideoFrame, 1.0 },
inferRequest{ inferRequest },
requireGettingNumberOfDetections{ true }
{
}
DetectionsProcessor(VideoFrame::Ptr sharedVideoFrame,
std::shared_ptr<ClassifiersAggregator>&& classifiersAggregator,
std::list<cv::Rect>&& vehicleRects,
std::list<cv::Rect>&& plateRects) :
Task{ sharedVideoFrame, 1.0 },
classifiersAggregator{ std::move(classifiersAggregator) },
inferRequest{ nullptr },
vehicleRects{ std::move(vehicleRects) },
plateRects{ std::move(plateRects) },
requireGettingNumberOfDetections{ false }
{
}
bool isReady() override;
void process() override;
private:
std::shared_ptr<ClassifiersAggregator> classifiersAggregator; // when no one stores this object we will draw
ov::InferRequest* inferRequest;
std::list<cv::Rect> vehicleRects;
std::list<cv::Rect> plateRects;
std::vector<std::reference_wrapper<ov::InferRequest>> reservedAttributesRequests;
std::vector<std::reference_wrapper<ov::InferRequest>> reservedLprRequests;
bool requireGettingNumberOfDetections;
};
// runs detection
class InferTask : public Task {
public:
explicit InferTask(VideoFrame::Ptr sharedVideoFrame) :
Task{ sharedVideoFrame, 5.0 } {}
bool isReady() override;
void process() override;
};
class Reader : public Task {
public:
explicit Reader(VideoFrame::Ptr sharedVideoFrame) :
Task{ sharedVideoFrame, 2.0 } {}
bool isReady() override;
void process() override;
};
class ANSLPR_API ANSALPR_OV :public ANSALPR {
private:
std::string _vehicleLPModel; //model that detects both vehicle and license plate
std::string _vehicleAtModel; //model that detects vehicle attributes
std::string _lprModel; //model that recognise license plate
Detector* _detector = nullptr;
VehicleAttributesClassifier* _vehicleAttributesClassifier = nullptr;
Lpr* _lpr = nullptr;
[[nodiscard]] std::string VectorDetectionToJsonString(const std::vector<ALPRObject>& dets);
public:
ANSALPR_OV();
~ANSALPR_OV();
[[nodiscard]] bool Initialize(const std::string& licenseKey, const std::string& modelZipFilePath, const std::string& modelZipPassword) override;
[[nodiscard]] bool Inference(const cv::Mat& input, std::string& lprResult);
[[nodiscard]] bool Inference(const cv::Mat& input, const std::vector<cv::Rect>& Bbox, std::string& lprResult);
[[nodiscard]] bool Destroy() override;
};
}
#endif