Files
ANSCustomModels/ANSCustomHelmetDetection/ANSCustomCodeHelmetDetection.cpp

258 lines
8.3 KiB
C++

#include "ANSCustomCodeHelmetDetection.h"
static std::string toUpperCase(const std::string& input) {
std::string result = input;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c) { return std::toupper(c); });
return result;
}
ANSCustomHMD::ANSCustomHMD() {
_isInitialized = false;
_readROIs = false;
}
ANSCustomHMD::~ANSCustomHMD() {
Destroy();
}
bool ANSCustomHMD::Destroy() {
try {
_detector.reset();
_classifier.reset();
_isInitialized = false;
return true;
}
catch (...) {
return false;
}
}
bool ANSCustomHMD::OptimizeModel(bool fp16) {
try {
if (!_detector || !_classifier) return false;
int detectorResult = _detector->Optimize(fp16);
int classifierResult = _classifier->Optimize(fp16);
if ((detectorResult != 1) || (classifierResult != 1)) return false;
else return true;
}
catch (...) {
return false;
}
}
bool ANSCustomHMD::Initialize(const std::string& modelDirectory, float detectionScoreThreshold, std::string& labelMap) {
try {
_modelDirectory = modelDirectory;
_detectionScoreThreshold = detectionScoreThreshold;
_isInitialized = false;
// Create model instances using factory pattern (ABI-safe)
_detector = ANSLIBPtr(ANSCENTER::ANSLIB::Create(), &ANSCENTER::ANSLIB::Destroy);
_classifier = ANSLIBPtr(ANSCENTER::ANSLIB::Create(), &ANSCENTER::ANSLIB::Destroy);
// NVIDIA GPU: Use TensorRT
_detectorModelType = 31; // TENSORRT
_detectorDetectionType = 1; // DETECTION
_classifierModelType = 31; // TENSORRT
_classifierDetectionType = 0; // CLASSIFICATION
//Check the hardware type
engineType = _detector->GetEngineType();
if (engineType == 1) {
// NVIDIA GPU: Use TensorRT
_detectorModelType = 31; // TENSORRT
_detectorDetectionType = 1; // DETECTION
_classifierModelType = 31; // TENSORRT
_classifierDetectionType = 0; // CLASSIFICATION
std::cout << "NVIDIA GPU detected. Using TensorRT" << std::endl;
}
else {
// CPU/Other: Use YOLO
_detectorModelType = 3; // YOLOV8/YOLOV11
_detectorDetectionType = 1; // DETECTION
_classifierModelType = 20; // ANSONNXCL
_classifierDetectionType = 0; // CLASSIFICATION
std::cout << "CPU detected. Using YOLO/ANSONNXCL" << std::endl;
}
if (_detectionScoreThreshold < 0.25f) _detectionScoreThreshold = 0.25f;
// classId: 0=license plate, 1=motorcyclist, 2=helmet, 3=no_helmet
labelMap = "license plate,motorcyclist,helmet,no_helmet";
#ifdef FNS_DEBUG
this->_loadEngineOnCreate = true;
#endif
int loadEngineOnCreation = _loadEngineOnCreate ? 1 : 0;
int autoEngineDetection = 1;
std::string licenseKey = "";
// Load detector model
float detScoreThreshold = _detectionScoreThreshold;
float detConfThreshold = 0.5f;
float detNMSThreshold = 0.5f;
std::string detLabelMap;
int detResult = _detector->LoadModelFromFolder(
licenseKey.c_str(),
"detector", "detector.names",
detScoreThreshold, detConfThreshold, detNMSThreshold,
autoEngineDetection,
_detectorModelType, _detectorDetectionType,
loadEngineOnCreation,
modelDirectory.c_str(),
detLabelMap);
if (detResult != 1) {
std::cerr << "ANSCustomHMD::Initialize: Failed to load detector model." << std::endl;
return false;
}
// Load classifier model
float clsScoreThreshold = 0.25f;
float clsConfThreshold = 0.5f;
float clsNMSThreshold = 0.5f;
int clsResult = _classifier->LoadModelFromFolder(
licenseKey.c_str(),
"classifier", "classifier.names",
clsScoreThreshold, clsConfThreshold, clsNMSThreshold,
autoEngineDetection,
_classifierModelType, _classifierDetectionType,
loadEngineOnCreation,
modelDirectory.c_str(),
_classifierLabels);
if (clsResult != 1) {
std::cerr << "ANSCustomHMD::Initialize: Failed to load classifier model." << std::endl;
return false;
}
_isInitialized = true;
return true;
}
catch (const std::exception& e) {
std::cerr << "ANSCustomHMD::Initialize: Exception: " << e.what() << std::endl;
return false;
}
catch (...) {
std::cerr << "ANSCustomHMD::Initialize: Unknown exception." << std::endl;
return false;
}
}
bool ANSCustomHMD::ConfigureParameters(CustomParams& param) {
param.ROI_Config.clear();
param.ROI_Options.clear();
param.Parameters.clear();
param.ROI_Values.clear();
return true;
}
std::vector<CustomObject> ANSCustomHMD::RunInference(const cv::Mat& input) {
return RunInference(input, "CustomCam");
}
std::vector<CustomObject> ANSCustomHMD::RunInference(const cv::Mat& input, const std::string& camera_id) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
if (!_isInitialized || !_detector) {
return {};
}
if (input.empty() || input.cols < 10 || input.rows < 10) {
return {};
}
try {
// One-time parameter reading
if (!_readROIs) {
for (const auto& param : _params.Parameters) {
if (param.Name.find("ALPR") != std::string::npos) {
std::string paramValue = toUpperCase(param.Value);
// ALPR feature currently disabled
}
}
_readROIs = true;
}
// Run object detection
std::vector<ANSCENTER::Object> detectionResults;
_detector->RunInference(input, camera_id.c_str(), detectionResults);
if (detectionResults.empty()) {
return {};
}
std::vector<CustomObject> results;
results.reserve(detectionResults.size());
const cv::Rect frameBounds(0, 0, input.cols, input.rows);
const float scoreThreshold = _detectionScoreThreshold;
for (const auto& obj : detectionResults) {
if (obj.confidence < scoreThreshold) {
continue;
}
CustomObject customObject;
customObject.confidence = obj.confidence;
customObject.box = obj.box;
customObject.cameraId = camera_id;
switch (obj.classId) {
case 0: { // License plate
customObject.classId = 0;
customObject.className = "license plate";
customObject.extraInfo = "license plate";
results.push_back(std::move(customObject));
break;
}
case 1: { // Motorcycle
customObject.classId = 1;
customObject.className = "motorcyclist";
results.push_back(std::move(customObject));
break;
}
case 2: // Helmet
case 3: { // No helmet - classify to confirm
// Validate bounding box
if ((obj.box & frameBounds) != obj.box) {
continue;
}
if (!_classifier) {
continue;
}
cv::Mat croppedImage = input(obj.box);
std::vector<ANSCENTER::Object> classifierResults;
_classifier->RunInference(croppedImage, camera_id.c_str(), classifierResults);
if (classifierResults.empty()) {
continue;
}
const bool isNoHelmet = (classifierResults[0].classId == 1);
customObject.classId = isNoHelmet ? 3 : 2;
customObject.className = isNoHelmet ? "no_helmet" : "helmet";
results.push_back(std::move(customObject));
break;
}
default:
break;
}
}
return results;
}
catch (const std::exception& e) {
std::cerr << "ANSCustomHMD::RunInference: Exception: " << e.what() << std::endl;
}
catch (...) {
std::cerr << "ANSCustomHMD::RunInference: Unknown exception." << std::endl;
}
return {};
}