#ifndef ANSLPR_H #define ANSLPR_H #define ANSLPR_API __declspec(dllexport) #pragma once #include #include #include #include #include #include #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) 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 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> 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& 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 _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 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 & Bbox, std::string& lprResult) = 0; [[nodiscard]] virtual bool Inference(const cv::Mat& input, const std::vector & Bbox, std::string& lprResult,const std::string & cameraId) = 0; [[nodiscard]] virtual std::vector RunInference(const cv::Mat& input, const std::string &cameraId) = 0; [[nodiscard]] std::string VectorDetectionToJsonString(const std::vector& dets); void SetPlateFormats(const std::vector& formats); void SetPlateFormat(const std::string& format); [[nodiscard]] std::vector 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 GetBoundingBoxes(const std::string& strBBoxes); [[nodiscard]] static std::string PolygonToString(const std::vector& polygon); [[nodiscard]] static std::string KeypointsToString(const std::vector& kps); [[nodiscard]] static std::vector 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 divideImage(const cv::Mat& image); [[nodiscard]] std::vector createSlideScreens(const cv::Mat& image); [[nodiscard]] int getHighestPriorityRegion(); [[nodiscard]] int getLowestPriorityRegion(); [[nodiscard]] cv::Rect getRegionByPriority(int priority); [[nodiscard]] std::vector AdjustLicensePlateBoundingBoxes(const std::vector& 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 // 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); #endif