使用 Qt C++与 Tesseract 搭建 OCR 识别项目

一、技术简述

OCR(光学字符识别)技术原理可以概括为:将图像中的文字区域检测出来,并将其中的字符形状转换成计算机可编辑的文本编码。其核心流程从输入图像到输出文本,通过机器学习或模式识别技术,对图像中的文字进行识别和转换

二、开发环境搭建

要使用 MSVC 方式编译运行

2.1 核心依赖库

Tesseract OCR:文字识别引擎,需要准备开发库(含头文件和 .lib/.a 文件)和语言数据包(如 chi_sim.traineddata)。
Leptonica:Tesseract 依赖的图像处理库,通常随 Tesseract 一起提供。
OpenCV (可选但推荐):用于图像预处理,提升识别准确率。

2.2 编译 OCR 所需的依赖库

2.2.1 采用 CMake 编译(麻烦)

https://blog.csdn.net/happydeer/article/details/141561569

1 编译 zlib
2 编译 libpng
3 编译 libjpeg
4 编译 libtiff
5 编译 webp
6 编译 leptonica
7 编译 tesseract

image

补充:SW 包管理工具

D:/soft/sw/sw.exe
文档较少、编译负责、建议使用vcpkg

2.2.2 采用 vcpkg 编译(推荐)

// 1. 安装 vcpkg
git clone https://github.com/microsoft/vcpkg
cd vcpkg
bootstrap-vcpkg.bat

// 2. 安装 OCR 库
vcpkg install tesseract:x64-windows

会自动安装:
tesseract
leptonica
libpng
libjpeg
libtiff
webp
zlib

全部自动编译。

# 安装目录:vcpkg/installed/x64-windows
installed
 ├─include
 │   ├─tesseract
 │   └─leptonica
 │
 ├─lib
 │   ├─tesseract41.lib
 │   └─leptonica-1.82.0.lib
 │
 └─bin
     ├─tesseract41.dll
     └─leptonica.dll

2.2.3 下载语言包

https://github.com/tesseract-ocr/tessdata

tessdata
 ├─eng.traineddata
 └─chi_sim.traineddata
// C++ 初始化语言包
Tesseract::TessBaseAPI api;
api.Init("./tessdata", "eng+chi_sim");

2.3 Qt 项目配置 (.pro 文件)

将下载的库文件放入项目目录,并修改 .pro 文件,添加头文件路径和库链接

# 配置 Tesseract 和 Leptonica 库
INCLUDEPATH += D:/vcpkg/installed/x64-windows/include

LIBS += \
    D:/vcpkg/installed/x64-windows/lib/tesseract41.lib \
    D:/vcpkg/installed/x64-windows/lib/leptonica-1.82.0.lib

2.4 运行时注意事项

动态链接库:需要将 tesseract41.dll、leptonica.dll 等文件复制到最终生成的可执行文件目录下。
语言包路径:程序运行时需要找到 tessdata 文件夹,里面存放 eng.traineddata(英文语言包)、chi_sim.traineddata(中文语言包) 等文件。

三、核心代码实现

3.1 在 Qt 项目中引入头文件

#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>
#include <opencv2/opencv.hpp>  //可选

3.2 Opencv 预处理

OpenCV 的预处理是 OCR 流程中至关重要的环节,合理的图像预处理能显著提升 Tesseract 等引擎的识别准确率。下面详细说明你列出的四个核心操作,并给出 C++ 代码示例和调参建议。


3.2.1 灰度转换(cv::cvtColor

目的:将彩色图像转为灰度图,减少颜色通道干扰,降低计算量。OCR 通常只关注亮度信息,颜色几乎不提供有用特征。

代码示例

cv::Mat img = cv::imread("input.jpg");
cv::Mat gray;
cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);

原理:灰度转换公式通常为 Y = 0.299*R + 0.587*G + 0.114*B,将 RGB 三个通道映射为一个亮度值(0~255)。


3.2.2 缩放图片(cv::resize

目的:将图像调整到合适的分辨率。过小的图像(如字体低于 20 像素)会导致字符细节丢失;过大的图像会降低处理速度且可能引入噪点。通常将文字高度缩放到 30~50 像素 左右可达到较好平衡。

代码示例

cv::Mat resized;
double scale_factor = 2.0;  // 根据需要调整
cv::resize(gray, resized, cv::Size(), scale_factor, scale_factor, cv::INTER_LINEAR);
// 或者指定目标宽度:
// cv::resize(gray, resized, cv::Size(800, 600));

注意:插值方法可选 INTER_LINEAR(默认,适合放大)或 INTER_CUBIC(更平滑)。对于文本,保持长宽比通常更为重要。


3.2.3 中值滤波(cv::medianBlur

目的:去除图像中的孤立噪点(如扫描仪的颗粒、屏幕截图时的像素杂点),同时尽量保持文字边缘清晰。中值滤波对椒盐噪声效果尤其好。

代码示例

cv::Mat denoised;
cv::medianBlur(resized, denoised, 3);  // 核大小通常为奇数,如 3、5

调参:核越大去噪越强,但可能模糊文字。对于高分辨率图像,核大小可设为 3 或 5;对于噪声严重的图像,可尝试 5。


3.2.4 自适应二值化(cv::adaptiveThreshold

目的:将灰度图转换为黑白二值图,使文字与背景对比最大化,便于 Tesseract 等算法提取字符轮廓。相比全局阈值,自适应二值化能处理光照不均匀的情况。

代码示例

cv::Mat binary;
cv::adaptiveThreshold(denoised, binary, 255, 
                      cv::ADAPTIVE_THRESH_GAUSSIAN_C, 
                      cv::THRESH_BINARY, 11, 2);

参数说明

  • 255:二值化后的最大值(白色)
  • ADAPTIVE_THRESH_GAUSSIAN_C:使用高斯加权邻域计算阈值(也可用 ADAPTIVE_THRESH_MEAN_C
  • THRESH_BINARY:二值化类型
  • 11:邻域块大小(奇数,决定局部区域范围),一般取 11~31 之间
  • 2:从均值或加权和中减去的常数,用来微调灵敏度

预处理流程组合示例

#include <opencv2/opencv.hpp>

cv::Mat preprocessForOCR(const std::string& imagePath) {
    cv::Mat img = cv::imread(imagePath);
    if (img.empty()) return cv::Mat();

    cv::Mat gray, resized, denoised, binary;

    // 1. 灰度化
    cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);

    // 2. 缩放(假设文字过小,放大2倍)
    cv::resize(gray, resized, cv::Size(), 2.0, 2.0, cv::INTER_LINEAR);

    // 3. 中值滤波去噪
    cv::medianBlur(resized, denoised, 3);

    // 4. 自适应二值化
    cv::adaptiveThreshold(denoised, binary, 255,
                          cv::ADAPTIVE_THRESH_GAUSSIAN_C,
                          cv::THRESH_BINARY, 11, 2);

    return binary;
}

为什么这些步骤对 OCR 重要?

操作 解决的问题 对 Tesseract 的影响
灰度转换 颜色干扰 聚焦文字形状,减少误判
缩放 文字过小或过大 保证字符细节清晰,适应引擎训练时的尺寸范围
中值滤波 噪点、颗粒 避免将噪点误认为字符笔画
自适应二值化 光照不均、背景复杂 形成清晰的文字/背景分割,提高字符定位精度

3.3 封装 OCR 识别函数

https://www.cnblogs.com/linuxAndMcu/p/19051355#_label0

#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>

int main() {
    // 初始化Tesseract API
    tesseract::TessBaseAPI *ocr = new tesseract::TessBaseAPI();

    // 初始化API,路径设置为tessdata目录的位置
    if (ocr->Init(NULL, "eng")) {
        fprintf(stderr, "Could not initialize tesseract.\n");
        return 1;
    }

    // 打开一个包含文字的图像文件
    Pix *image = pixRead("E:\\Learn\\learnGit\\untitled2\\ditto.png");
    ocr->SetImage(image);

    // 获取识别出的文本
    char *text = ocr->GetUTF8Text();
    printf("识别出的文本: %s\n", text);

    // 清理内存
    delete [] text;
    pixDestroy(&image);
    ocr->End();

    return 0;
}

posted @ 2026-03-24 10:35  twjy  阅读(185)  评论(0)    收藏  举报