如何在C++中提升Tesseract OCR对旋转图像的识别准确率?
如何在C++中提升Tesseract OCR对旋转图像的识别准确率?
嘿,我之前也踩过Tesseract处理任意角度旋转图像的坑!PSM_AUTO_OSD确实只擅长处理90°、180°这类整数倍的旋转,碰到任意倾斜的文本就容易拉胯。下面是我亲测有效的几个解决思路,你可以试试:
1. 先做图像倾斜校正(核心步骤)
Tesseract的方向检测模块对非90°倍数的倾斜支持很差,所以第一步得用OpenCV先把图像转正。我当时用的是基于轮廓最小外接矩形的方法来计算倾斜角度,然后旋转校正:
#include <opencv2/opencv.hpp> #include <tesseract/baseapi.h> #include <algorithm> // 计算图像的倾斜角度 double getSkewAngle(cv::Mat &img) { // 转灰度图+二值化 cv::Mat gray, binary; cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY); cv::threshold(gray, binary, 0, 255, cv::THRESH_BINARY_INV + cv::THRESH_OTSU); // 过滤小轮廓,只保留有效文本轮廓 std::vector<std::vector<cv::Point>> contours; cv::findContours(binary, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); contours.erase(std::remove_if(contours.begin(), contours.end(), [](const std::vector<cv::Point>& c) { return cv::contourArea(c) < 100; }), contours.end()); if (contours.empty()) return 0.0; // 取最大轮廓的最小外接矩形计算角度 auto largestContour = *std::max_element(contours.begin(), contours.end(), [](const std::vector<cv::Point>& a, const std::vector<cv::Point>& b) { return cv::contourArea(a) < cv::contourArea(b); }); cv::RotatedRect rect = cv::minAreaRect(largestContour); double angle = rect.angle; // 调整角度范围,确保旋转后文本正向 if (angle < -45) angle += 90; return -angle; } // 旋转图像并校正倾斜 cv::Mat deskewImage(cv::Mat &img, double angle) { cv::Point2f center(img.cols / 2.0, img.rows / 2.0); cv::Mat rotMat = cv::getRotationMatrix2D(center, angle, 1.0); cv::Mat deskewed; cv::warpAffine(img, deskewed, rotMat, img.size(), cv::INTER_CUBIC, cv::BORDER_REPLICATE); return deskewed; }
把图像转正后再喂给Tesseract,识别准确率会提升一大截!
2. 优化Tesseract的配置参数
除了PSM_AUTO_OSD,还要搭配合适的OEM模式和其他参数:
- 强制使用LSTM引擎(Tesseract 5默认是,但显式设置更稳妥):
tess->SetOEMMode(tesseract::OEM_LSTM_ONLY); - 如果校正后的图像文本规整,可以试试
PSM_SINGLE_BLOCK或者PSM_AUTO,有时候比PSM_AUTO_OSD更稳定 - 针对噪点多的图像,可以关闭系统词典减少干扰:
tess->SetVariable("load_system_dawg", "false");(按需使用)
完整调用示例:
int main() { cv::Mat img = cv::imread("rotated_text.jpg"); double skewAngle = getSkewAngle(img); cv::Mat deskewedImg = deskewImage(img, skewAngle); // 初始化Tesseract tesseract::TessBaseAPI tess; if (tess.Init(nullptr, "eng", tesseract::OEM_LSTM_ONLY)) { std::cerr << "初始化Tesseract失败!" << std::endl; return -1; } tess.SetPageSegMode(tesseract::PSM_AUTO); tess.SetImage(deskewedImg.data, deskewedImg.cols, deskewedImg.rows, 3, deskewedImg.step); // 识别文本 char* outText = tess.GetUTF8Text(); std::cout << "识别结果:\n" << outText << std::endl; // 释放资源 tess.End(); delete[] outText; return 0; }
3. 增强图像预处理效果
如果旋转后的图像有模糊、噪点,先做预处理优化:
- 高斯模糊去噪:
cv::GaussianBlur(gray, gray, cv::Size(3,3), 0); - 自适应二值化(适配光照不均的场景):
cv::adaptiveThreshold(gray, binary, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY_INV, 11, 2); - 去除小噪点:用开运算过滤,
cv::morphologyEx(binary, binary, cv::MORPH_OPEN, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(2,2)));
这些步骤能让Tesseract更容易捕捉到文本的清晰特征。
备注:内容来源于stack exchange,提问作者OMKAR GULAMBE
相关产品推荐
相关产品推荐

