Initial OCR to support ALPR mode with country support

This commit is contained in:
2026-03-29 22:51:39 +11:00
parent 6861de8fb4
commit b735931c55
13 changed files with 911 additions and 27 deletions

View File

@@ -6,6 +6,7 @@
#include "ANSRtOCR.h"
#include "ANSLibsLoader.h"
#include "ANSGpuFrameRegistry.h"
#include <json.hpp>
#include "NV12PreprocessHelper.h"
#include <unordered_map>
#include <condition_variable>
@@ -234,6 +235,19 @@ extern "C" ANSOCR_API int CreateANSOCRHandle(ANSCENTER::ANSOCRBase** Handle, co
classifierThreshold, useDilation, 960);
}
// Helper: serialize OCR results with optional ALPR post-processing
static std::string SerializeOCRResults(ANSCENTER::ANSOCRBase* engine,
const std::vector<ANSCENTER::OCRObject>& outputs, int imageWidth, int imageHeight,
const cv::Mat& originalImage = cv::Mat()) {
if (engine->GetOCRMode() == ANSCENTER::OCR_ALPR && !engine->GetALPRFormats().empty()) {
auto alprResults = ANSCENTER::ANSOCRUtility::ALPRPostProcessing(
outputs, engine->GetALPRFormats(), imageWidth, imageHeight,
engine, originalImage);
return ANSCENTER::ANSOCRUtility::ALPRResultToJsonString(alprResults);
}
return ANSCENTER::ANSOCRUtility::OCRDetectionToJsonString(outputs);
}
extern "C" ANSOCR_API std::string RunInference(ANSCENTER::ANSOCRBase** Handle, unsigned char* jpeg_string, int32 bufferLength) {
if (!Handle || !*Handle) return "";
OCRHandleGuard guard(AcquireOCRHandle(*Handle));
@@ -243,7 +257,7 @@ extern "C" ANSOCR_API std::string RunInference(ANSCENTER::ANSOCRBase** Handle,
cv::Mat frame = cv::imdecode(cv::Mat(1, bufferLength, CV_8UC1, jpeg_string), cv::IMREAD_COLOR);
if (frame.empty()) return "";
std::vector<ANSCENTER::OCRObject> outputs = engine->RunInference(frame);
std::string stResult = ANSCENTER::ANSOCRUtility::OCRDetectionToJsonString(outputs);
std::string stResult = SerializeOCRResults(engine, outputs, frame.cols, frame.rows, frame);
frame.release();
outputs.clear();
return stResult;
@@ -260,7 +274,7 @@ extern "C" ANSOCR_API std::string RunInferenceWithCamID(ANSCENTER::ANSOCRBase**
cv::Mat frame = cv::imdecode(cv::Mat(1, bufferLength, CV_8UC1, jpeg_string), cv::IMREAD_COLOR);
if (frame.empty()) return "";
std::vector<ANSCENTER::OCRObject> outputs = engine->RunInference(frame, cameraId);
std::string stResult = ANSCENTER::ANSOCRUtility::OCRDetectionToJsonString(outputs);
std::string stResult = SerializeOCRResults(engine, outputs, frame.cols, frame.rows, frame);
frame.release();
outputs.clear();
return stResult;
@@ -276,7 +290,7 @@ extern "C" ANSOCR_API int RunInferenceCV(ANSCENTER::ANSOCRBase** Handle, const c
try {
if (image.empty()) return 0;
std::vector<ANSCENTER::OCRObject> outputs = engine->RunInference(image, "cameraId");
ocrResult = ANSCENTER::ANSOCRUtility::OCRDetectionToJsonString(outputs);
ocrResult = SerializeOCRResults(engine, outputs, image.cols, image.rows, image);
return 1;
}
catch (...) { return -2; }
@@ -291,7 +305,7 @@ extern "C" ANSOCR_API std::string RunInferenceBinary(ANSCENTER::ANSOCRBase** Ha
cv::Mat frame = cv::Mat(height, width, CV_8UC3, jpeg_bytes).clone();
if (frame.empty()) return "";
std::vector<ANSCENTER::OCRObject> outputs = engine->RunInference(frame);
std::string stResult = ANSCENTER::ANSOCRUtility::OCRDetectionToJsonString(outputs);
std::string stResult = SerializeOCRResults(engine, outputs, width, height, frame);
frame.release();
outputs.clear();
return stResult;
@@ -325,6 +339,62 @@ extern "C" ANSOCR_API int ReleaseANSOCRHandle(ANSCENTER::ANSOCRBase** Handle) {
}
}
// ── ALPR Configuration API ──────────────────────────────────────────
extern "C" ANSOCR_API int SetANSOCRMode(ANSCENTER::ANSOCRBase** Handle, int ocrMode) {
if (!Handle || !*Handle) return -1;
(*Handle)->SetOCRMode(static_cast<ANSCENTER::OCRMode>(ocrMode));
return 0;
}
extern "C" ANSOCR_API int SetANSOCRALPRCountry(ANSCENTER::ANSOCRBase** Handle, int country) {
if (!Handle || !*Handle) return -1;
(*Handle)->SetALPRCountry(static_cast<ANSCENTER::ALPRCountry>(country));
return 0;
}
extern "C" ANSOCR_API int SetANSOCRALPRFormat(ANSCENTER::ANSOCRBase** Handle, const char* formatJson) {
if (!Handle || !*Handle || !formatJson) return -1;
try {
nlohmann::json j = nlohmann::json::parse(formatJson);
ANSCENTER::ALPRPlateFormat fmt;
fmt.name = j.value("name", "CUSTOM");
fmt.country = static_cast<ANSCENTER::ALPRCountry>(j.value("country", 99));
fmt.numRows = j.value("num_rows", 2);
fmt.rowSplitThreshold = j.value("row_split_threshold", 0.3f);
static const std::map<std::string, ANSCENTER::ALPRCharClass> classMap = {
{"digit", ANSCENTER::CHAR_DIGIT}, {"latin_alpha", ANSCENTER::CHAR_LATIN_ALPHA},
{"alphanumeric", ANSCENTER::CHAR_ALPHANUMERIC}, {"hiragana", ANSCENTER::CHAR_HIRAGANA},
{"katakana", ANSCENTER::CHAR_KATAKANA}, {"kanji", ANSCENTER::CHAR_KANJI},
{"cjk_any", ANSCENTER::CHAR_CJK_ANY}, {"any", ANSCENTER::CHAR_ANY}
};
for (const auto& zj : j["zones"]) {
ANSCENTER::ALPRZone zone;
zone.name = zj.value("name", "");
zone.row = zj.value("row", 0);
zone.col = zj.value("col", 0);
std::string ccStr = zj.value("char_class", "any");
auto it = classMap.find(ccStr);
zone.charClass = (it != classMap.end()) ? it->second : ANSCENTER::CHAR_ANY;
zone.minLength = zj.value("min_length", 1);
zone.maxLength = zj.value("max_length", 10);
zone.validationRegex = zj.value("regex", "");
if (zj.contains("corrections")) {
for (auto& [key, val] : zj["corrections"].items()) {
zone.corrections[key] = val.get<std::string>();
}
}
fmt.zones.push_back(zone);
}
(*Handle)->SetALPRFormat(fmt);
return 0;
} catch (...) {
return -2;
}
}
extern "C" ANSOCR_API std::string RunInferenceImagePath(ANSCENTER::ANSOCRBase** Handle, const char* imageFilePath) {
if (!Handle || !*Handle) return "";
OCRHandleGuard guard(AcquireOCRHandle(*Handle));
@@ -335,7 +405,7 @@ extern "C" ANSOCR_API std::string RunInferenceImagePath(ANSCENTER::ANSOCRBase**
cv::Mat frame = cv::imread(stImageFileName, cv::ImreadModes::IMREAD_COLOR);
if (frame.empty()) return "";
std::vector<ANSCENTER::OCRObject> outputs = engine->RunInference(frame);
std::string stResult = ANSCENTER::ANSOCRUtility::OCRDetectionToJsonString(outputs);
std::string stResult = SerializeOCRResults(engine, outputs, frame.cols, frame.rows, frame);
frame.release();
outputs.clear();
return stResult;