Fix mutex lock issues
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "ANSLPR_OCR.h"
|
||||
#include "ANSRTYOLO.h"
|
||||
#include "ANSONNXYOLO.h"
|
||||
#include "ANSOnnxOCR.h"
|
||||
#include "ANSOCRBase.h"
|
||||
@@ -20,6 +21,59 @@ static void WriteEventLog(const char* message, WORD eventType = EVENTLOG_INFORMA
|
||||
OutputDebugStringA("\n");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SEH wrapper for loading ANSRTYOLO (TensorRT) models — used when NVIDIA GPU
|
||||
// is detected. Falls back to ANSONNXYOLO if TRT fails.
|
||||
// ---------------------------------------------------------------------------
|
||||
struct LoadRtParams_OCR {
|
||||
const std::string* licenseKey;
|
||||
ANSCENTER::ModelConfig* config;
|
||||
const std::string* modelFolder;
|
||||
const char* modelName;
|
||||
const char* classFile;
|
||||
std::string* labels;
|
||||
std::unique_ptr<ANSCENTER::ANSODBase>* detector;
|
||||
bool enableTracker;
|
||||
bool disableStabilization;
|
||||
};
|
||||
|
||||
static bool LoadRtModel_OCR_Impl(const LoadRtParams_OCR& p) {
|
||||
try {
|
||||
auto rtyolo = std::make_unique<ANSCENTER::ANSRTYOLO>();
|
||||
bool ok = rtyolo->LoadModelFromFolder(
|
||||
*p.licenseKey, *p.config, p.modelName, p.classFile,
|
||||
*p.modelFolder, *p.labels);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
if (p.enableTracker) {
|
||||
rtyolo->SetTracker(ANSCENTER::TrackerType::BYTETRACK, true);
|
||||
} else {
|
||||
rtyolo->SetTracker(ANSCENTER::TrackerType::BYTETRACK, false);
|
||||
}
|
||||
if (p.disableStabilization) {
|
||||
rtyolo->SetStabilization(false);
|
||||
}
|
||||
*p.detector = std::move(rtyolo);
|
||||
return true;
|
||||
}
|
||||
catch (...) {
|
||||
p.detector->reset();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool LoadRtModel_OCR_SEH(const LoadRtParams_OCR& p, DWORD* outCode) {
|
||||
*outCode = 0;
|
||||
__try {
|
||||
return LoadRtModel_OCR_Impl(p);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
*outCode = GetExceptionCode();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
struct LoadOnnxParams_OCR {
|
||||
const std::string* licenseKey;
|
||||
ANSCENTER::ModelConfig* config;
|
||||
@@ -186,40 +240,81 @@ namespace ANSCENTER
|
||||
|
||||
bool valid = false;
|
||||
|
||||
// ── Step 2: Load LP detector with ONNX Runtime ───────────────
|
||||
// ── Step 2: Load LP detector ─────────────────────────────────
|
||||
if (FileExist(lprModel)) {
|
||||
WriteEventLog("ANSALPR_OCR::LoadEngine: Step 2 - Loading LP detector with ONNX Runtime");
|
||||
this->_logger.LogInfo("ANSALPR_OCR::LoadEngine", "Step 2: Loading LP detector with ONNX Runtime", __FILE__, __LINE__);
|
||||
_lpdmodelConfig.detectionType = DetectionType::DETECTION;
|
||||
_lpdmodelConfig.modelType = ModelType::ONNXYOLO;
|
||||
std::string _lprClasses;
|
||||
{
|
||||
LoadOnnxParams_OCR p{};
|
||||
p.licenseKey = &_licenseKey;
|
||||
p.config = &_lpdmodelConfig;
|
||||
p.modelFolder = &_modelFolder;
|
||||
p.modelName = "lpd";
|
||||
p.classFile = "lpd.names";
|
||||
p.labels = &_lprClasses;
|
||||
p.detector = &_lpDetector;
|
||||
p.enableTracker = true;
|
||||
p.disableStabilization = true;
|
||||
// Try TensorRT (ANSRTYOLO) when NVIDIA GPU is detected
|
||||
if (engineType == EngineType::NVIDIA_GPU) {
|
||||
WriteEventLog("ANSALPR_OCR::LoadEngine: Step 2 - Loading LP detector with TensorRT");
|
||||
this->_logger.LogInfo("ANSALPR_OCR::LoadEngine", "Step 2: Loading LP detector with TensorRT", __FILE__, __LINE__);
|
||||
_lpdmodelConfig.detectionType = DetectionType::DETECTION;
|
||||
_lpdmodelConfig.modelType = ModelType::RTYOLO;
|
||||
std::string _lprClasses;
|
||||
{
|
||||
LoadRtParams_OCR p{};
|
||||
p.licenseKey = &_licenseKey;
|
||||
p.config = &_lpdmodelConfig;
|
||||
p.modelFolder = &_modelFolder;
|
||||
p.modelName = "lpd";
|
||||
p.classFile = "lpd.names";
|
||||
p.labels = &_lprClasses;
|
||||
p.detector = &_lpDetector;
|
||||
p.enableTracker = true;
|
||||
p.disableStabilization = true;
|
||||
|
||||
DWORD sehCode = 0;
|
||||
bool lpSuccess = LoadOnnxModel_OCR_SEH(p, &sehCode);
|
||||
if (sehCode != 0) {
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"ANSALPR_OCR::LoadEngine: Step 2 LPD SEH exception 0x%08X — LP detector disabled", sehCode);
|
||||
WriteEventLog(buf, EVENTLOG_ERROR_TYPE);
|
||||
this->_logger.LogFatal("ANSALPR_OCR::LoadEngine",
|
||||
"Step 2: LP detector crashed (SEH). LP detector disabled.", __FILE__, __LINE__);
|
||||
if (_lpDetector) _lpDetector.reset();
|
||||
DWORD sehCode = 0;
|
||||
bool lpSuccess = LoadRtModel_OCR_SEH(p, &sehCode);
|
||||
if (sehCode != 0) {
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"ANSALPR_OCR::LoadEngine: Step 2 LPD TRT SEH exception 0x%08X — falling back to ONNX Runtime", sehCode);
|
||||
WriteEventLog(buf, EVENTLOG_ERROR_TYPE);
|
||||
this->_logger.LogError("ANSALPR_OCR::LoadEngine",
|
||||
"Step 2: LP detector TensorRT crashed (SEH). Falling back to ONNX Runtime.", __FILE__, __LINE__);
|
||||
if (_lpDetector) _lpDetector.reset();
|
||||
}
|
||||
else if (!lpSuccess) {
|
||||
this->_logger.LogError("ANSALPR_OCR::LoadEngine",
|
||||
"Failed to load LP detector (TensorRT). Falling back to ONNX Runtime.", __FILE__, __LINE__);
|
||||
if (_lpDetector) _lpDetector.reset();
|
||||
}
|
||||
}
|
||||
else if (!lpSuccess) {
|
||||
this->_logger.LogError("ANSALPR_OCR::LoadEngine",
|
||||
"Failed to load LP detector (ONNX Runtime).", __FILE__, __LINE__);
|
||||
if (_lpDetector) _lpDetector.reset();
|
||||
}
|
||||
|
||||
// Fallback to ONNX Runtime (ANSONNXYOLO) if TRT was not attempted or failed
|
||||
if (!_lpDetector) {
|
||||
WriteEventLog("ANSALPR_OCR::LoadEngine: Step 2 - Loading LP detector with ONNX Runtime");
|
||||
this->_logger.LogInfo("ANSALPR_OCR::LoadEngine", "Step 2: Loading LP detector with ONNX Runtime", __FILE__, __LINE__);
|
||||
_lpdmodelConfig.detectionType = DetectionType::DETECTION;
|
||||
_lpdmodelConfig.modelType = ModelType::ONNXYOLO;
|
||||
std::string _lprClasses;
|
||||
{
|
||||
LoadOnnxParams_OCR p{};
|
||||
p.licenseKey = &_licenseKey;
|
||||
p.config = &_lpdmodelConfig;
|
||||
p.modelFolder = &_modelFolder;
|
||||
p.modelName = "lpd";
|
||||
p.classFile = "lpd.names";
|
||||
p.labels = &_lprClasses;
|
||||
p.detector = &_lpDetector;
|
||||
p.enableTracker = true;
|
||||
p.disableStabilization = true;
|
||||
|
||||
DWORD sehCode = 0;
|
||||
bool lpSuccess = LoadOnnxModel_OCR_SEH(p, &sehCode);
|
||||
if (sehCode != 0) {
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"ANSALPR_OCR::LoadEngine: Step 2 LPD SEH exception 0x%08X — LP detector disabled", sehCode);
|
||||
WriteEventLog(buf, EVENTLOG_ERROR_TYPE);
|
||||
this->_logger.LogFatal("ANSALPR_OCR::LoadEngine",
|
||||
"Step 2: LP detector crashed (SEH). LP detector disabled.", __FILE__, __LINE__);
|
||||
if (_lpDetector) _lpDetector.reset();
|
||||
}
|
||||
else if (!lpSuccess) {
|
||||
this->_logger.LogError("ANSALPR_OCR::LoadEngine",
|
||||
"Failed to load LP detector (ONNX Runtime).", __FILE__, __LINE__);
|
||||
if (_lpDetector) _lpDetector.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -302,37 +397,77 @@ namespace ANSCENTER
|
||||
|
||||
// ── Step 4: Load colour classifier (optional) ────────────────
|
||||
if (FileExist(colorModel) && (_lpColourModelConfig.detectionScoreThreshold > 0)) {
|
||||
WriteEventLog("ANSALPR_OCR::LoadEngine: Step 4 - Loading colour classifier with ONNX Runtime");
|
||||
this->_logger.LogInfo("ANSALPR_OCR::LoadEngine", "Step 4: Loading colour classifier with ONNX Runtime", __FILE__, __LINE__);
|
||||
_lpColourModelConfig.detectionType = DetectionType::CLASSIFICATION;
|
||||
_lpColourModelConfig.modelType = ModelType::ONNXYOLO;
|
||||
{
|
||||
LoadOnnxParams_OCR p{};
|
||||
p.licenseKey = &_licenseKey;
|
||||
p.config = &_lpColourModelConfig;
|
||||
p.modelFolder = &_modelFolder;
|
||||
p.modelName = "lpc";
|
||||
p.classFile = "lpc.names";
|
||||
p.labels = &_lpColourLabels;
|
||||
p.detector = &_lpColourDetector;
|
||||
p.enableTracker = false;
|
||||
p.disableStabilization = false;
|
||||
// Try TensorRT (ANSRTYOLO) when NVIDIA GPU is detected
|
||||
if (engineType == EngineType::NVIDIA_GPU) {
|
||||
WriteEventLog("ANSALPR_OCR::LoadEngine: Step 4 - Loading colour classifier with TensorRT");
|
||||
this->_logger.LogInfo("ANSALPR_OCR::LoadEngine", "Step 4: Loading colour classifier with TensorRT", __FILE__, __LINE__);
|
||||
_lpColourModelConfig.detectionType = DetectionType::CLASSIFICATION;
|
||||
_lpColourModelConfig.modelType = ModelType::RTYOLO;
|
||||
{
|
||||
LoadRtParams_OCR p{};
|
||||
p.licenseKey = &_licenseKey;
|
||||
p.config = &_lpColourModelConfig;
|
||||
p.modelFolder = &_modelFolder;
|
||||
p.modelName = "lpc";
|
||||
p.classFile = "lpc.names";
|
||||
p.labels = &_lpColourLabels;
|
||||
p.detector = &_lpColourDetector;
|
||||
p.enableTracker = false;
|
||||
p.disableStabilization = false;
|
||||
|
||||
DWORD sehCode = 0;
|
||||
bool colourSuccess = LoadOnnxModel_OCR_SEH(p, &sehCode);
|
||||
if (sehCode != 0) {
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"ANSALPR_OCR::LoadEngine: Step 4 LPC SEH exception 0x%08X — colour detection disabled", sehCode);
|
||||
WriteEventLog(buf, EVENTLOG_ERROR_TYPE);
|
||||
this->_logger.LogError("ANSALPR_OCR::LoadEngine",
|
||||
"Step 4: Colour classifier crashed. Colour detection disabled.", __FILE__, __LINE__);
|
||||
if (_lpColourDetector) _lpColourDetector.reset();
|
||||
DWORD sehCode = 0;
|
||||
bool colourSuccess = LoadRtModel_OCR_SEH(p, &sehCode);
|
||||
if (sehCode != 0) {
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"ANSALPR_OCR::LoadEngine: Step 4 LPC TRT SEH exception 0x%08X — falling back to ONNX Runtime", sehCode);
|
||||
WriteEventLog(buf, EVENTLOG_ERROR_TYPE);
|
||||
this->_logger.LogError("ANSALPR_OCR::LoadEngine",
|
||||
"Step 4: Colour classifier TensorRT crashed (SEH). Falling back to ONNX Runtime.", __FILE__, __LINE__);
|
||||
if (_lpColourDetector) _lpColourDetector.reset();
|
||||
}
|
||||
else if (!colourSuccess) {
|
||||
this->_logger.LogError("ANSALPR_OCR::LoadEngine",
|
||||
"Failed to load colour classifier (TensorRT). Falling back to ONNX Runtime.", __FILE__, __LINE__);
|
||||
if (_lpColourDetector) _lpColourDetector.reset();
|
||||
}
|
||||
}
|
||||
else if (!colourSuccess) {
|
||||
this->_logger.LogError("ANSALPR_OCR::LoadEngine",
|
||||
"Failed to load colour detector (ONNX Runtime). Colour detection disabled.", __FILE__, __LINE__);
|
||||
if (_lpColourDetector) _lpColourDetector.reset();
|
||||
}
|
||||
|
||||
// Fallback to ONNX Runtime (ANSONNXYOLO) if TRT was not attempted or failed
|
||||
if (!_lpColourDetector) {
|
||||
WriteEventLog("ANSALPR_OCR::LoadEngine: Step 4 - Loading colour classifier with ONNX Runtime");
|
||||
this->_logger.LogInfo("ANSALPR_OCR::LoadEngine", "Step 4: Loading colour classifier with ONNX Runtime", __FILE__, __LINE__);
|
||||
_lpColourModelConfig.detectionType = DetectionType::CLASSIFICATION;
|
||||
_lpColourModelConfig.modelType = ModelType::ONNXYOLO;
|
||||
{
|
||||
LoadOnnxParams_OCR p{};
|
||||
p.licenseKey = &_licenseKey;
|
||||
p.config = &_lpColourModelConfig;
|
||||
p.modelFolder = &_modelFolder;
|
||||
p.modelName = "lpc";
|
||||
p.classFile = "lpc.names";
|
||||
p.labels = &_lpColourLabels;
|
||||
p.detector = &_lpColourDetector;
|
||||
p.enableTracker = false;
|
||||
p.disableStabilization = false;
|
||||
|
||||
DWORD sehCode = 0;
|
||||
bool colourSuccess = LoadOnnxModel_OCR_SEH(p, &sehCode);
|
||||
if (sehCode != 0) {
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"ANSALPR_OCR::LoadEngine: Step 4 LPC SEH exception 0x%08X — colour detection disabled", sehCode);
|
||||
WriteEventLog(buf, EVENTLOG_ERROR_TYPE);
|
||||
this->_logger.LogError("ANSALPR_OCR::LoadEngine",
|
||||
"Step 4: Colour classifier crashed. Colour detection disabled.", __FILE__, __LINE__);
|
||||
if (_lpColourDetector) _lpColourDetector.reset();
|
||||
}
|
||||
else if (!colourSuccess) {
|
||||
this->_logger.LogError("ANSALPR_OCR::LoadEngine",
|
||||
"Failed to load colour detector (ONNX Runtime). Colour detection disabled.", __FILE__, __LINE__);
|
||||
if (_lpColourDetector) _lpColourDetector.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,13 +14,13 @@ namespace ANSCENTER { class ANSONNXOCR; struct OCRModelConfig; }
|
||||
|
||||
namespace ANSCENTER
|
||||
{
|
||||
/// ANSALPR_OCR — License plate recognition using ONNX YOLO for LP detection
|
||||
/// ANSALPR_OCR — License plate recognition using YOLO for LP detection
|
||||
/// and ANSONNXOCR (PaddleOCR v5) for text recognition.
|
||||
///
|
||||
/// Pipeline:
|
||||
/// 1. Detect license plates using _lpDetector (ANSONNXYOLO)
|
||||
/// 1. Detect license plates using _lpDetector (ANSRTYOLO on NVIDIA GPU, ANSONNXYOLO otherwise)
|
||||
/// 2. For each detected plate, run OCR using _ocrEngine (ANSONNXOCR)
|
||||
/// 3. Optionally classify plate colour using _lpColourDetector (ANSONNXYOLO)
|
||||
/// 3. Optionally classify plate colour using _lpColourDetector (ANSRTYOLO on NVIDIA GPU, ANSONNXYOLO otherwise)
|
||||
///
|
||||
/// Supports multiple countries via the Country enum and ALPR post-processing
|
||||
/// from ANSOCR's ANSOCRBase infrastructure.
|
||||
|
||||
Reference in New Issue
Block a user