Fix NV12 crash issue when recreate camera object
This commit is contained in:
@@ -863,7 +863,8 @@ namespace ANSCENTER {
|
||||
}
|
||||
}
|
||||
std::vector<Object> ANSALPR_OD::RunInferenceSingleFrame(const cv::Mat& input, const std::string& cameraId) {
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
// No coarse _mutex here — sub-components (detectors, alprChecker) have their own locks.
|
||||
// LabVIEW semaphore controls concurrency at the caller level.
|
||||
|
||||
// Early validation
|
||||
if (!_licenseValid) {
|
||||
@@ -916,18 +917,19 @@ namespace ANSCENTER {
|
||||
cv::Mat draw = input.clone();
|
||||
#endif
|
||||
|
||||
_detectedArea = cv::Rect(0, 0, frameWidth, frameHeight);
|
||||
// Use local variable instead of shared _detectedArea for thread safety
|
||||
cv::Rect detectedArea(0, 0, frameWidth, frameHeight);
|
||||
|
||||
if (_detectedArea.width <= 50 || _detectedArea.height <= 50) {
|
||||
if (detectedArea.width <= 50 || detectedArea.height <= 50) {
|
||||
return {};
|
||||
}
|
||||
|
||||
#ifdef FNS_DEBUG
|
||||
cv::rectangle(draw, _detectedArea, cv::Scalar(0, 0, 255), 2);
|
||||
cv::rectangle(draw, detectedArea, cv::Scalar(0, 0, 255), 2);
|
||||
#endif
|
||||
|
||||
// Run license plate detection
|
||||
cv::Mat activeFrame = frame(_detectedArea);
|
||||
cv::Mat activeFrame = frame(detectedArea);
|
||||
std::vector<Object> lprOutput = _lpDetector->RunInference(activeFrame, cameraId);
|
||||
|
||||
if (lprOutput.empty()) {
|
||||
@@ -1010,7 +1012,7 @@ namespace ANSCENTER {
|
||||
return {};
|
||||
}
|
||||
std::string ANSALPR_OD::DetectLicensePlateString(const cv::Mat& lprROI, const std::string& cameraId) {
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
// No coarse _mutex — _ocrDetector has its own m_inferenceMutex
|
||||
try {
|
||||
// convert lprROI to greyscale if it is not already
|
||||
if (lprROI.empty()) {
|
||||
@@ -1277,8 +1279,7 @@ namespace ANSCENTER {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
|
||||
// No coarse _mutex — _lpColourDetector has its own m_inferenceMutex
|
||||
try {
|
||||
std::vector<Object> colourOutputs = _lpColourDetector->RunInference(lprROI, cameraId);
|
||||
|
||||
@@ -1310,8 +1311,9 @@ namespace ANSCENTER {
|
||||
return DetectLPColourDetector(lprROI, cameraId);
|
||||
}
|
||||
|
||||
// Check cache first (no GPU work needed)
|
||||
// Check cache first (fine-grained lock, no GPU work)
|
||||
{
|
||||
std::lock_guard<std::mutex> cacheLock(_colourCacheMutex);
|
||||
auto it = _colourCache.find(plateText);
|
||||
if (it != _colourCache.end()) {
|
||||
it->second.hitCount++;
|
||||
@@ -1319,11 +1321,12 @@ namespace ANSCENTER {
|
||||
}
|
||||
}
|
||||
|
||||
// Cache miss — run the actual classifier
|
||||
// Cache miss — run the actual classifier (no lock held during GPU inference)
|
||||
std::string colour = DetectLPColourDetector(lprROI, cameraId);
|
||||
|
||||
// Store in cache
|
||||
// Store in cache (fine-grained lock)
|
||||
if (!colour.empty()) {
|
||||
std::lock_guard<std::mutex> cacheLock(_colourCacheMutex);
|
||||
if (_colourCache.size() >= COLOUR_CACHE_MAX_SIZE) {
|
||||
_colourCache.clear();
|
||||
}
|
||||
@@ -1334,13 +1337,14 @@ namespace ANSCENTER {
|
||||
}
|
||||
|
||||
bool ANSALPR_OD::Inference(const cv::Mat& input, std::string& lprResult) {
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
// No coarse _mutex — delegates to Inference(input, lprResult, cameraId) which is also lock-free
|
||||
if (input.empty()) return false;
|
||||
if ((input.cols < 5) || (input.rows < 5)) return false;
|
||||
return Inference(input, lprResult, "CustomCam");
|
||||
}
|
||||
bool ANSALPR_OD::Inference(const cv::Mat& input, std::string& lprResult, const std::string& cameraId) {
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
// No coarse _mutex — sub-components have their own fine-grained locks.
|
||||
// LabVIEW semaphore controls concurrency at the caller level.
|
||||
|
||||
// Early validation
|
||||
if (!_licenseValid) {
|
||||
@@ -1518,14 +1522,14 @@ namespace ANSCENTER {
|
||||
}
|
||||
}
|
||||
bool ANSALPR_OD::Inference(const cv::Mat& input, const std::vector<cv::Rect> & Bbox, std::string& lprResult) {
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
// No coarse _mutex — delegates to Inference(input, Bbox, lprResult, cameraId)
|
||||
if (input.empty()) return false;
|
||||
if ((input.cols < 5) || (input.rows < 5)) return false;
|
||||
return Inference(input, Bbox, lprResult, "CustomCam");
|
||||
}
|
||||
bool ANSALPR_OD::Inference(const cv::Mat& input, const std::vector<cv::Rect>& Bbox,std::string& lprResult, const std::string& cameraId)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
// No coarse _mutex — sub-components have their own fine-grained locks.
|
||||
|
||||
// Early validation
|
||||
if (!_licenseValid) {
|
||||
@@ -2177,12 +2181,10 @@ namespace ANSCENTER {
|
||||
cv::Mat unsharp;
|
||||
cv::addWeighted(denoised, 1.8, blurred, -0.8, 0, unsharp);
|
||||
|
||||
// Step 5: CLAHE contrast enhancement
|
||||
if (!_clahe) {
|
||||
_clahe = cv::createCLAHE(4.0, cv::Size(8, 8));
|
||||
}
|
||||
// Step 5: CLAHE contrast enhancement (thread-local for thread safety)
|
||||
thread_local cv::Ptr<cv::CLAHE> tl_clahe = cv::createCLAHE(4.0, cv::Size(8, 8));
|
||||
cv::Mat contrastEnhanced;
|
||||
_clahe->apply(unsharp, contrastEnhanced);
|
||||
tl_clahe->apply(unsharp, contrastEnhanced);
|
||||
|
||||
// Step 6: Laplacian edge sharpening
|
||||
cv::Mat lap;
|
||||
@@ -2718,6 +2720,7 @@ namespace ANSCENTER {
|
||||
|
||||
void ANSALPR_OD::ensureUniquePlateText(std::vector<Object>& results, const std::string& cameraId)
|
||||
{
|
||||
std::lock_guard<std::mutex> plateLock(_plateIdentitiesMutex);
|
||||
auto& identities = _plateIdentities[cameraId];
|
||||
|
||||
// Option B: Auto-detect mode by counting detections.
|
||||
|
||||
Reference in New Issue
Block a user