Support tracker to improve ALPR_OCR
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -45,6 +46,66 @@ namespace ANSCENTER
|
||||
|
||||
ALPRChecker alprChecker;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Full-frame vs pipeline auto-detection (ported from ANSALPR_OD)
|
||||
//
|
||||
// When the caller feeds ANSLPR_OCR pre-cropped vehicle ROIs (each
|
||||
// frame is a different small image), the tracker can't work — the
|
||||
// LP detector sees a totally new image every call so trackIds mean
|
||||
// nothing. In that "pipeline" mode we must skip the ALPRChecker
|
||||
// voting layer entirely and return raw OCR results.
|
||||
//
|
||||
// When the caller feeds full-frame video (same resolution every
|
||||
// frame, plates moving through the scene), the tracker works
|
||||
// normally and we run plate text through ALPRChecker majority
|
||||
// voting + spatial dedup to stabilise readings.
|
||||
//
|
||||
// Mode is auto-detected by watching whether consecutive frames
|
||||
// share the exact same (width, height) for at least
|
||||
// CONFIRM_THRESHOLD frames. Pipeline crops vary by a few pixels;
|
||||
// full-frame video is pixel-identical.
|
||||
// ----------------------------------------------------------------
|
||||
struct ImageSizeTracker {
|
||||
cv::Size lastSize{ 0, 0 };
|
||||
int consistentCount = 0;
|
||||
bool detectedFullFrame = false;
|
||||
static constexpr int CONFIRM_THRESHOLD = 5;
|
||||
static constexpr int MIN_FULLFRAME_WIDTH = 1000;
|
||||
};
|
||||
std::unordered_map<std::string, ImageSizeTracker> _imageSizeTrackers;
|
||||
|
||||
[[nodiscard]] bool shouldUseALPRChecker(const cv::Size& imageSize,
|
||||
const std::string& cameraId);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Spatial plate identity persistence (ported from ANSALPR_OD)
|
||||
//
|
||||
// Prevents the same plate string from appearing on two different
|
||||
// vehicles in the same frame. The LP tracker may briefly assign
|
||||
// the same trackId to two different plates when vehicles pass
|
||||
// each other, or two different trackIds to the same plate when
|
||||
// occlusion breaks a track. In either case, OCR can produce the
|
||||
// same text for two spatial locations for a frame or two — which
|
||||
// looks like "plate flicker" in the UI.
|
||||
//
|
||||
// ensureUniquePlateText() resolves the ambiguity by accumulating
|
||||
// confidence per spatial location. When two detections share a
|
||||
// plate text, the one whose spatial history has the higher score
|
||||
// wins and the other has its className cleared.
|
||||
// ----------------------------------------------------------------
|
||||
struct SpatialPlateIdentity {
|
||||
cv::Point2f center; // plate center in frame coords
|
||||
std::string plateText;
|
||||
float accumulatedScore = 0.0f;
|
||||
int framesSinceLastSeen = 0;
|
||||
};
|
||||
std::mutex _plateIdentitiesMutex;
|
||||
std::unordered_map<std::string, std::vector<SpatialPlateIdentity>> _plateIdentities;
|
||||
static constexpr float PLATE_SPATIAL_MATCH_THRESHOLD = 0.3f; // IoU threshold
|
||||
|
||||
void ensureUniquePlateText(std::vector<Object>& results,
|
||||
const std::string& cameraId);
|
||||
|
||||
// --- Original model zip path (reused for ANSONNXOCR initialization) ---
|
||||
std::string _modelZipFilePath;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user