Files
ANSCORE/modules/ANSLPR/ANSLPR.h

149 lines
9.6 KiB
C
Raw Normal View History

2026-03-28 16:54:11 +11:00
#ifndef ANSLPR_H
#define ANSLPR_H
#define ANSLPR_API __declspec(dllexport)
#pragma once
#include <iostream>
#include <cassert>
#include <fstream>
#include <string>
#include <filesystem>
#include <opencv2/opencv.hpp>
#include "Utility.h"
#include "ANSLicense.h"
#include "LabVIEWHeader/extcode.h"
#include "ANSEngineCommon.h"
#define MAX_ALPR_FRAME 60
namespace ANSCENTER
{
// Country enum is now defined in ANSLicense.h (ANSCENTER namespace)
2026-03-28 16:54:11 +11:00
class ALPRChecker {
private:
int maxFrames;
int minVotesToStabilize = 3; // need at least 3 identical reads to lock
float iouMatchThreshold = 0.3f; // IoU to match same physical plate across frames
std::recursive_mutex _mutex;
// Per-plate spatial tracking: each tracked plate has a location + text history
struct TrackedPlate {
cv::Rect lastBox;
std::deque<std::string> textHistory; // rolling history of OCR reads
std::string lockedText; // majority-vote winner (empty = not locked yet)
int lockCount = 0; // how many consecutive frames the lock held
int framesSinceLastSeen = 0; // how many checkPlate calls since this plate was last matched
};
int _pruneCounter = 0; // counts checkPlate calls for periodic pruning
// cameraId -> list of tracked plates
std::unordered_map<std::string, std::vector<TrackedPlate>> trackedPlates;
[[nodiscard]] int levenshteinDistance(const std::string& s1, const std::string& s2);
[[nodiscard]] float computeIoU(const cv::Rect& a, const cv::Rect& b);
[[nodiscard]] std::string majorityVote(const std::deque<std::string>& history);
public:
void Init(int framesToStore = MAX_ALPR_FRAME);
ALPRChecker(int framesToStore = MAX_ALPR_FRAME) : maxFrames(framesToStore) {}
// Original API (backward compatible) — no spatial tracking
[[nodiscard]] std::string checkPlate(const std::string& cameraId, const std::string& detectedPlate);
// Enhanced API with bounding box for spatial plate tracking
[[nodiscard]] std::string checkPlate(const std::string& cameraId, const std::string& detectedPlate, const cv::Rect& plateBox);
};
class ANSLPR_API ANSALPR {
protected:
SPDLogger& _logger = SPDLogger::GetInstance("ALPR", false);
bool _debugFlag{ false };
bool _licenseValid{ false };
bool _isInitialized{ false};
double _detectorThreshold{ 0.5 };
double _ocrThreshold{ 0.5 };
double _colorThreshold{ 0.0 };// If we use the colour information, this threshold should be greater than 0.0
std::vector<std::string> _plateFormats;
std::string _licenseKey{};
std::string _modelFolder;
struct ImageSection {
cv::Rect region;
int priority;
ImageSection(const cv::Rect& r) : region(r), priority(0) {}
};
cv::Size previousImageSize = cv::Size(0, 0);
std::vector<ImageSection> cachedSections;
int _currentPriority{ 0 }; // None
cv::Rect _detectedArea;// Area where license plate are detected
Country _country;
std::recursive_mutex _mutex;
public:
[[nodiscard]] virtual bool Initialize(const std::string& licenseKey, const std::string& modelZipFilePath, const std::string& modelZipPassword, double detectorThreshold, double ocrThreshold, double colourTheshold=0);
[[nodiscard]] virtual bool LoadEngine();
[[nodiscard]] virtual bool Inference(const cv::Mat& input, std::string& lprResult) = 0;
[[nodiscard]] virtual bool Inference(const cv::Mat& input, std::string& lprResult,const std::string &cameraId) = 0;
[[nodiscard]] virtual bool Inference(const cv::Mat& input, const std::vector<cv::Rect> & Bbox, std::string& lprResult) = 0;
[[nodiscard]] virtual bool Inference(const cv::Mat& input, const std::vector<cv::Rect> & Bbox, std::string& lprResult,const std::string & cameraId) = 0;
[[nodiscard]] virtual std::vector<Object> RunInference(const cv::Mat& input, const std::string &cameraId) = 0;
[[nodiscard]] std::string VectorDetectionToJsonString(const std::vector<Object>& dets);
void SetPlateFormats(const std::vector<std::string>& formats);
void SetPlateFormat(const std::string& format);
[[nodiscard]] std::vector<std::string> GetPlateFormats() const;
virtual ~ANSALPR();
void CheckLicense();
/// Enable/disable deep pipeline benchmarking.
/// When enabled, logs per-stage timing for the full ALPR pipeline
/// (LP detection, OCR, color classification, validation, serialization).
/// Also propagates the flag to sub-detectors (_lpDetector, _ocrDetector, etc.).
virtual void ActivateDebugger(bool debugFlag) { _debugFlag = debugFlag; }
[[nodiscard]] virtual bool Destroy() = 0;
[[nodiscard]] static std::vector<cv::Rect> GetBoundingBoxes(const std::string& strBBoxes);
[[nodiscard]] static std::string PolygonToString(const std::vector<cv::Point2f>& polygon);
[[nodiscard]] static std::string KeypointsToString(const std::vector<float>& kps);
[[nodiscard]] static std::vector<cv::Point2f> RectToNormalizedPolygon(const cv::Rect& rect, float imageWidth, float imageHeight);
protected:
// Utilities for scanning license plate
// Function to seperate screen size
[[nodiscard]] double calculateDistanceToCenter(const cv::Point& center, const cv::Rect& rect);
[[nodiscard]] std::vector<ImageSection> divideImage(const cv::Mat& image);
[[nodiscard]] std::vector<ANSALPR::ImageSection> createSlideScreens(const cv::Mat& image);
[[nodiscard]] int getHighestPriorityRegion();
[[nodiscard]] int getLowestPriorityRegion();
[[nodiscard]] cv::Rect getRegionByPriority(int priority);
[[nodiscard]] std::vector<Object> AdjustLicensePlateBoundingBoxes(const std::vector<Object>& detectionsInROI,
const cv::Rect& roi, const cv::Size& fullImageSize,
float aspectRatio = 2.0f, // width at least 2x height
int padding = 10 // base padding
);
};
}
extern "C" ANSLPR_API int CreateANSALPRHandle(ANSCENTER::ANSALPR **Handle, const char* licenseKey, const char* modelZipFilePath, const char* modelZipPassword, int engineType, double detectorThreshold, double ocrThreshold, double colourThreshold);
extern "C" ANSLPR_API int LoadANSALPREngineHandle(ANSCENTER::ANSALPR** Handle);
extern "C" ANSLPR_API std::string ANSALPR_RunInference(ANSCENTER::ANSALPR **Handle, unsigned char* jpeg_string, unsigned int bufferLength);
extern "C" ANSLPR_API std::string ANSALPR_RunInferenceWithCamID(ANSCENTER::ANSALPR** Handle, unsigned char* jpeg_string, unsigned int bufferLength, const char* cameraId);
extern "C" ANSLPR_API std::string ANSALPR_RunInferenceBinary(ANSCENTER::ANSALPR * *Handle, unsigned char* jpeg_bytes, unsigned int width, unsigned int height);
extern "C" ANSLPR_API std::string ANSALPR_RunInferenceBinaryInCroppedImages(ANSCENTER::ANSALPR * *Handle, unsigned char* jpeg_bytes, unsigned int width, unsigned int height, const char* strBboxes);
extern "C" ANSLPR_API std::string ANSALPR_RunInferenceInCroppedImages(ANSCENTER::ANSALPR** Handle, unsigned char* jpeg_string, unsigned int bufferLength, const char* strBboxes);
extern "C" ANSLPR_API std::string ANSALPR_RunInferenceInCroppedImagesWithCamID(ANSCENTER::ANSALPR** Handle, unsigned char* jpeg_string, unsigned int bufferLength, const char* strBboxes, const char* cameraId);
extern "C" ANSLPR_API int ReleaseANSALPRHandle(ANSCENTER::ANSALPR **Handle);
//// For LabVIEW API
extern "C" ANSLPR_API int ANSALPR_RunInference_LV(ANSCENTER::ANSALPR **Handle, unsigned char* jpeg_string, unsigned int bufferLength, LStrHandle detectionResult);
extern "C" ANSLPR_API int ANSALPR_RunInferenceWithCamID_LV(ANSCENTER::ANSALPR** Handle, unsigned char* jpeg_string, unsigned int bufferLength, const char* cameraId, LStrHandle detectionResult);
extern "C" ANSLPR_API int ANSALPR_RunInferenceBinary_LV(ANSCENTER::ANSALPR * *Handle, unsigned char* jpeg_bytes, unsigned int width, unsigned int height, LStrHandle detectionResult);
extern "C" ANSLPR_API int ANSALPR_RunInferenceInCroppedImages_LV(ANSCENTER::ANSALPR * *Handle, unsigned char* jpeg_string, unsigned int bufferLength, const char* strBboxes, LStrHandle detectionResult);
extern "C" ANSLPR_API int ANSALPR_RunInferenceInCroppedImagesWithCamID_LV(ANSCENTER::ANSALPR** Handle, unsigned char* jpeg_string, unsigned int bufferLength, const char* strBboxes, const char* cameraId, LStrHandle detectionResult);
extern "C" ANSLPR_API int ANSALPR_RunInferenceComplete_LV(ANSCENTER::ANSALPR** Handle, cv::Mat** cvImage, const char* cameraId, int getJpegString, int jpegImageSize, LStrHandle detectionResult, LStrHandle imageStr);
extern "C" ANSLPR_API int ANSALPR_RunInferenceComplete_CPP(ANSCENTER::ANSALPR** Handle, cv::Mat** cvImage, const char* cameraId, int getJpegString, int jpegImageSize,std::string& detectionResult, std::string& imageStr);
extern "C" ANSLPR_API int ANSALPR_RunInferencesComplete_LV(ANSCENTER::ANSALPR** Handle, cv::Mat** cvImage, const char* cameraId, int maxImageSize,const char* strBboxes, LStrHandle detectionResult);
// Get/Set format
extern "C" ANSLPR_API int ANSALPR_SetFormat(ANSCENTER::ANSALPR** Handle, const char* format);
extern "C" ANSLPR_API int ANSALPR_SetFormats(ANSCENTER::ANSALPR** Handle, const char* formats);// comma separated formats
extern "C" ANSLPR_API int ANSALPR_GetFormats(ANSCENTER::ANSALPR** Handle, LStrHandle formats);// comma separated formats
2026-03-31 14:10:21 +11:00
// Unicode conversion utilities for LabVIEW wrapper classes
extern "C" ANSLPR_API int ANSLPR_ConvertUTF8ToUTF16LE(const char* utf8Str, LStrHandle result);
extern "C" ANSLPR_API int ANSLPR_ConvertUTF16LEToUTF8(const unsigned char* utf16leBytes, int byteLen, LStrHandle result);
2026-03-28 16:54:11 +11:00
#endif