Improve ALPR_OCR peformance

This commit is contained in:
2026-04-14 20:30:21 +10:00
parent 3349b45ade
commit f9a0af8949
18 changed files with 991 additions and 77 deletions

View File

@@ -3805,6 +3805,149 @@ int ALPR_OCR_Test() {
return 0;
}
int ALPR_OCR_VideoTest() {
std::cout << "=== ALPR_OCR_VideoTest: ANSALPR_OCR engine on video ===" << std::endl;
std::filesystem::path currentPath = std::filesystem::current_path();
std::cout << "Current working directory: " << currentPath << std::endl;
ANSCENTER::ANSALPR* infHandle = nullptr;
std::string licenseKey = "";
std::string modelFilePath = "C:\\Projects\\ANSVIS\\Models\\ANS_GenericALPR_v2.0.zip";
std::string videoFilePath = "E:\\Programs\\DemoAssets\\Videos\\ALRP\\PMH\\Day\\day.mp4";
int engineType = 2; // ANSALPR_OCR
double detectionThreshold = 0.3;
double ocrThreshold = 0.5;
double colourThreshold = 0.0;
// Step 1: Create handle
int createResult = CreateANSALPRHandle(&infHandle, licenseKey.c_str(),
modelFilePath.c_str(), "", engineType, detectionThreshold, ocrThreshold, colourThreshold);
std::cout << "CreateANSALPRHandle result: " << createResult << std::endl;
if (!createResult || !infHandle) {
std::cerr << "Failed to create ANSALPR_OCR handle" << std::endl;
return -1;
}
// Step 2: Set country (JAPAN = 5 — adjust to match the dataset if needed)
ANSALPR_SetCountry(&infHandle, 5);
std::cout << "Country set to JAPAN" << std::endl;
// Step 3: Load engine
auto engineStart = std::chrono::high_resolution_clock::now();
int loadResult = LoadANSALPREngineHandle(&infHandle);
auto engineEnd = std::chrono::high_resolution_clock::now();
double engineMs = std::chrono::duration<double, std::milli>(engineEnd - engineStart).count();
std::cout << "LoadANSALPREngineHandle result: " << loadResult << " (" << engineMs << " ms)" << std::endl;
if (!loadResult) {
std::cerr << "Failed to load ANSALPR_OCR engine" << std::endl;
ReleaseANSALPRHandle(&infHandle);
return -2;
}
// Step 4: Open video
cv::VideoCapture capture(videoFilePath);
if (!capture.isOpened()) {
std::cerr << "Could not open video file: " << videoFilePath << std::endl;
ReleaseANSALPRHandle(&infHandle);
return -3;
}
boost::property_tree::ptree pt;
int frameIdx = 0;
while (true) {
cv::Mat frame;
if (!capture.read(frame)) {
std::cout << "\nEnd of video stream.\n";
break;
}
++frameIdx;
int width = frame.cols;
int height = frame.rows;
// Convert to raw BGR bytes for ANSALPR_RunInferenceBinary
unsigned int bufferLength = static_cast<unsigned int>(frame.total() * frame.elemSize());
unsigned char* imageBytes = new unsigned char[bufferLength];
std::memcpy(imageBytes, frame.data, bufferLength);
auto t0 = std::chrono::high_resolution_clock::now();
std::string detectionResult = ANSALPR_RunInferenceBinary(&infHandle, imageBytes, width, height);
auto t1 = std::chrono::high_resolution_clock::now();
double inferMs = std::chrono::duration<double, std::milli>(t1 - t0).count();
delete[] imageBytes;
printf("Frame %d: %.2f ms (%.1f FPS)\n", frameIdx, inferMs,
inferMs > 0.0 ? (1000.0 / inferMs) : 0.0);
// Draw detections
if (!detectionResult.empty()) {
try {
pt.clear();
std::stringstream ss(detectionResult);
boost::property_tree::read_json(ss, pt);
BOOST_FOREACH(const boost::property_tree::ptree::value_type& child, pt.get_child("results")) {
const boost::property_tree::ptree& res = child.second;
const auto class_name_raw = GetData<std::string>(res, "class_name");
const std::string class_name = DecodeUnicodeEscapes(class_name_raw);
const auto x = GetData<int>(res, "x");
const auto y = GetData<int>(res, "y");
const auto w = GetData<int>(res, "width");
const auto h = GetData<int>(res, "height");
cv::rectangle(frame, cv::Rect(x, y, w, h), cv::Scalar(0, 255, 0), 2);
std::string extraInfo = GetOptionalValue<std::string>(res, "extra_info", "");
if (!class_name.empty()) {
std::cout << " Plate: " << class_name;
if (!extraInfo.empty()) std::cout << " (" << extraInfo << ")";
std::cout << std::endl;
}
#ifdef WIN32
{
int textH = (int)(1.5 * 30);
int ty = y - 5 - textH;
if (ty < 0) ty = y + 3;
putTextUnicode(frame, class_name, cv::Point(x, ty),
1.5, cv::Scalar(0, 0, 255), 3);
}
#else
cv::putText(frame, class_name, cv::Point(x, y - 5),
cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
#endif
}
}
catch (const std::exception& e) {
std::cerr << "JSON parse error: " << e.what() << std::endl;
}
}
// Display (fit to 1920x1080)
cv::Mat display;
double scale = std::min(1920.0 / frame.cols, 1080.0 / frame.rows);
if (scale < 1.0) {
cv::resize(frame, display, cv::Size(), scale, scale);
} else {
display = frame;
}
cv::namedWindow("ALPR_OCR_VideoTest", cv::WINDOW_AUTOSIZE);
cv::imshow("ALPR_OCR_VideoTest", display);
if (cv::waitKey(1) == 27) { // ESC to exit
std::cout << "ESC pressed — stopping.\n";
break;
}
}
capture.release();
cv::destroyAllWindows();
ReleaseANSALPRHandle(&infHandle);
std::cout << "=== ALPR_OCR_VideoTest complete ===" << std::endl;
return 0;
}
int main()
{
#ifdef WIN32
@@ -3825,7 +3968,8 @@ int main()
//ANSLPR_MultiGPU_StressTest_SimulatedCam();
// ANSLPR_MultiGPU_StressTest_FilePlayer();
//ANSLPR_OD_CPU_VideoTest();
ALPR_OCR_Test();
//ALPR_OCR_Test();
ALPR_OCR_VideoTest();
return 0;
}