Files
EasyOCR-CPP/DLLUsageDemo/DLLUsageDemo.cpp
T
2026-07-17 15:50:06 +08:00

168 lines
5.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// DLLUsageDemo.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <set>
#include <iostream>
#include "LibEasyOCR-CPP.h"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <range/v3/view/enumerate.hpp>
#include <opencv2/photo/photo.hpp>
#include <opencv2/features2d.hpp>
static const std::set<char> 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<uchar>(i) = cv::saturate_cast<uchar>(std::pow(i / 255.0, gamma) * 255);
cv::LUT(gray, lut, gray);
// 4. CLAHE 局部对比度增强
cv::Ptr<cv::CLAHE> 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::vector<std::string> 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);
uns::EasyOCR_CPP::SetRecognitionModel(recognize_model, uns::easyocr::CharsetType::EN);
if (!uns::EasyOCR_CPP::InitDetectionModel())
{
std::cout << "Detector Init Failure!" << std::endl;
return -1;
}
if (!uns::EasyOCR_CPP::InitRecognitionModel())
{
std::cout << "Recognizer Init Failure!" << std::endl;
return -2;
}
for (auto&& [index, file] : images | ranges::views::enumerate)
RecognizeSingleImage(file, static_cast<int>(index));
cv::waitKey(0);
uns::EasyOCR_CPP::CleanupOCR();
return 0;
}
//VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV