From 7f30fb78a4e018dbf4f8323115cb36537b4eda52 Mon Sep 17 00:00:00 2001 From: UnknownObject Date: Fri, 17 Jul 2026 15:50:06 +0800 Subject: [PATCH] push --- DLLUsageDemo/DLLUsageDemo.cpp | 150 ++++++++++++++++++++++++++++++---- EasyOCR-CPP/EasyOCR-CPP.cpp | 10 ++- EasyOCR-CPP/OCRCharset.cpp | 27 ++++++ EasyOCR-CPP/OCRCharset.h | 2 + 4 files changed, 174 insertions(+), 15 deletions(-) diff --git a/DLLUsageDemo/DLLUsageDemo.cpp b/DLLUsageDemo/DLLUsageDemo.cpp index 5c0fb05..1230d8c 100644 --- a/DLLUsageDemo/DLLUsageDemo.cpp +++ b/DLLUsageDemo/DLLUsageDemo.cpp @@ -1,16 +1,146 @@ // DLLUsageDemo.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // +#include #include #include "LibEasyOCR-CPP.h" #include #include +#include +#include +#include + +static const std::set validate_vin_chars = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z' }; + +std::string PreProcessVIN(const std::string& vin) +{ + std::string res; + for (const auto& chr : vin) + { + if ((chr == 'i') || (chr == 'I')) + res.push_back('1'); + else if ((chr == 'o') || (chr == 'O')) + res.push_back('0'); + else if (chr == 'q') + res.push_back('9'); + else if (chr == 'Q') + res.push_back('0'); + else if (validate_vin_chars.count(toupper(chr)) >= 1) + res.push_back(toupper(chr)); + } + return res; +} + +void RecognizeSingleImage(const std::string& img, int image_no) +{ + cv::Mat image = cv::imread(img); + if (image.empty()) + { + std::cout << "RSI: Unable to read image" << std::endl; + return; + } + + //cv::blur(image, image, cv::Size(3, 3)); + + // 1. 灰度 + cv::Mat gray; + cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY); + + // 2. 去高光(inpaint) + cv::Mat mask = gray > 240; + cv::inpaint(gray, mask, gray, 5, cv::INPAINT_TELEA); + + // 3. 伽马校正(弱化阴影) + cv::Mat lut(1, 256, CV_8U); + const float gamma = 0.8f; + for (int i = 0; i < 256; i++) + lut.at(i) = cv::saturate_cast(std::pow(i / 255.0, gamma) * 255); + cv::LUT(gray, lut, gray); + + // 4. CLAHE 局部对比度增强 + cv::Ptr clahe = cv::createCLAHE(2.0, cv::Size(8, 8)); + clahe->apply(gray, gray); + + // 2. 形态学 Top-hat & Black-hat 提取高频细节 + cv::Mat kernel = cv::getStructuringElement( + cv::MORPH_RECT, cv::Size(15, 15)); + cv::Mat tophat, blackhat; + cv::morphologyEx(gray, tophat, cv::MORPH_TOPHAT, kernel); + cv::morphologyEx(gray, blackhat, cv::MORPH_BLACKHAT, kernel); + + // 3. 高频增强:原图 + tophat - blackhat + cv::Mat enhanced; + enhanced = gray + tophat - blackhat; + + // 4. 平滑降噪 + cv::GaussianBlur(enhanced, enhanced, cv::Size(3, 3), 0); + + // 5. 全局 Otsu 阈值 + cv::Mat bw; + cv::threshold( + enhanced, bw, + 0, 255, + cv::THRESH_BINARY | cv::THRESH_OTSU + ); + // 保证文字白底黑字 + double m = cv::mean(bw.row(bw.rows / 2))[0]; + if (m < 128) cv::bitwise_not(bw, bw); + + // 6. 小核闭运算补笔画断裂 + cv::morphologyEx( + bw, bw, + cv::MORPH_CLOSE, + cv::getStructuringElement( + cv::MORPH_RECT, cv::Size(3, 3) + ), + cv::Point(-1, -1), 1 + ); + + // 7. 小核开运算去孤立噪点 + cv::morphologyEx( + bw, bw, + cv::MORPH_OPEN, + cv::getStructuringElement( + cv::MORPH_RECT, cv::Size(3, 3) + ), + cv::Point(-1, -1), 1 + ); + + // 8. 转三通道输出 + cv::Mat finalBGR; + cv::cvtColor(bw, finalBGR, cv::COLOR_GRAY2BGR); + + cv::Mat output = finalBGR.clone(); + + cv::imshow("Processed Image " + std::to_string(image_no), output); + cv::imwrite("G:\\Users\\15819\\Desktop\\temp\\Processed Image " + std::to_string(image_no) + ".jpg", output); + + auto results = uns::EasyOCR_CPP::FullAuto(image); + for (const auto& [index, info] : results) + { + const auto& [text, conf, rect] = info; + std::string a_text = uns::EOCR_SupportTools::WtoA(text); + std::string processed_vin = PreProcessVIN(a_text); + printf("RSI(%d): Result %d: Text = {%s(%d) -> |%s|(%d)}, Box = [%d, %d, %d, %d], Confidence = %.3f\n", image_no, (int)index, a_text.c_str(), (int)a_text.length(), processed_vin.c_str(), (int)processed_vin.length(), rect.tl().x, rect.tl().y, rect.br().x, rect.br().y, conf); + } + if (results.empty()) + printf("RSI(%d): No Text Found\n", image_no); +} int main() { std::wstring detect_model = L"..\\EasyOCR-CPP\\DetectionModel.onnx"; std::wstring recognize_model = L"..\\EasyOCR-CPP\\RecognitionModel-EN.onnx"; - std::string image = "..\\..\\vin.jpg"; + + std::vector images = + { + "G:\\Users\\15819\\Desktop\\error\\UPLOAD-20250709184942-99F24141-6C0A31D2.jpg", + "G:\\Users\\15819\\Desktop\\error\\UPLOAD-20250709185025-99F24141-A56037A2.jpg", + "G:\\Users\\15819\\Desktop\\error\\UPLOAD-20250709185205-99F24141-1D0C341A.jpg", + "G:\\Users\\15819\\Desktop\\error\\UPLOAD-20250709185450-99F24141-EC43D7FD.jpg", + "G:\\Users\\15819\\Desktop\\error\\UPLOAD-20250708185403-99F24141-1F2233FA.jpg", + "G:\\Users\\15819\\Desktop\\error\\UPLOAD-20250708184942-99F24141-C138BA94.jpg" + }; uns::EasyOCR_CPP::GlobalOCRConfig().SetDetectModelPath(detect_model); uns::EasyOCR_CPP::GlobalOCRConfig().SetGPUUsage(uns::easyocr::GPUUsage::CPUOnly); @@ -27,20 +157,12 @@ int main() return -2; } - cv::Mat img = uns::EOCR_SupportTools::ReadImage(image, true); - if (img.empty()) - { - std::cerr << "Failed to load image: " << image << std::endl; - return -1; - } - - auto results = uns::EasyOCR_CPP::FullAuto(img); - for (const auto& [index, info] : results) - { - const auto& [text, conf, rect] = info; - printf("Result %d: Text = {%s}, Box = [%d, %d, %d, %d], Confidence = %.3f\n", (int)index, uns::EOCR_SupportTools::WtoA(text).c_str(), rect.tl().x, rect.tl().y, rect.br().x, rect.br().y, conf); - } + for (auto&& [index, file] : images | ranges::views::enumerate) + RecognizeSingleImage(file, static_cast(index)); + cv::waitKey(0); uns::EasyOCR_CPP::CleanupOCR(); return 0; } + +//VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV \ No newline at end of file diff --git a/EasyOCR-CPP/EasyOCR-CPP.cpp b/EasyOCR-CPP/EasyOCR-CPP.cpp index 62bdf3f..f60b194 100644 --- a/EasyOCR-CPP/EasyOCR-CPP.cpp +++ b/EasyOCR-CPP/EasyOCR-CPP.cpp @@ -5,13 +5,15 @@ #include #include "EasyOCR_Detector.h" #include "EasyOCR_Recognizer.h" +#include "OCRCharset.h" int main() { const std::wstring detModelPath = L".\\DetectionModel.onnx"; const std::wstring recModelPath = L".\\RecognitionModel-EN.onnx"; const std::wstring recModelWithChnPath = L".\\RecognitionModel_EN+CH_SIM.onnx"; - const std::string imagePath = "..\\..\\vin-err.jpg"; + //const std::string imagePath = "..\\..\\vin-err.jpg"; + const std::string imagePath = "G:\\Users\\15819\\Desktop\\error\\UPLOAD-20250709185205-99F24141-1D0C341A.jpg"; //Init Config uns::G_OCRConfig.SetGPUUsage(uns::OCRConfig::GPUUsage::CPUOnly); @@ -35,6 +37,12 @@ int main() return -2; } + if (!uns::OCRCharset::CheckCharSet()) + { + std::cout << "Charset Error" << std::endl; + return -3; + } + //Load Image cv::Mat image = cv::imread(imagePath); if (image.empty()) diff --git a/EasyOCR-CPP/OCRCharset.cpp b/EasyOCR-CPP/OCRCharset.cpp index 58de7e6..7c59fed 100644 --- a/EasyOCR-CPP/OCRCharset.cpp +++ b/EasyOCR-CPP/OCRCharset.cpp @@ -68,6 +68,7 @@ std::map uns::OCRCharset::en_charmap = {60, L"P"}, {61, L"Q"}, {62, L"R"}, + {63, L"S"}, {64, L"T"}, {65, L"U"}, {66, L"V"}, @@ -6826,6 +6827,32 @@ std::map uns::OCRCharset::ch_en_charmap = {6718, L""} }; +bool uns::OCRCharset::CheckCharSet() +{ + size_t siz_en = en_charmap.size(); + size_t siz_ch_en = ch_en_charmap.size(); + + bool success_en = true, success_ch_en = true; + + for (size_t i = 0; i < siz_en; i++) + if (en_charmap.find(i) == en_charmap.end()) + { + std::cout << "EN CharMap: Error at " << i << std::endl; + success_en = false; + } + + for (size_t i = 0; i < siz_ch_en; i++) + if (ch_en_charmap.find(i) == ch_en_charmap.end()) + { + std::cout << "CH+EN CharMap: Error at " << i << std::endl; + success_ch_en = false; + } + + std::cout << "Charset Check: EN: " << (success_en ? "Success" : "Failure") << ", CH+EN: " << (success_en ? "Success" : "Failure") << std::endl; + + return (success_en && success_ch_en); +} + std::wstring uns::OCRCharset::GetChar(int index) { if (index == 0) diff --git a/EasyOCR-CPP/OCRCharset.h b/EasyOCR-CPP/OCRCharset.h index 7e35370..97d27c7 100644 --- a/EasyOCR-CPP/OCRCharset.h +++ b/EasyOCR-CPP/OCRCharset.h @@ -16,6 +16,8 @@ namespace uns OCRCharset(const OCRCharset&) = delete; public: + static bool CheckCharSet(); + static std::wstring GetChar(int index); static std::wstring GetString(const std::vector& indexs); };