前言
在當今數字化時代,文字識別(OCR)技術已經滲透到我們生活和工作的方方面面,從掃描文檔的自動排版到車牌識別、票據信息提取等,都離不開 OCR 技術的支持。而在眾多 OCR 實現方案中,QtC++ 結合 tesseract 和 OpenCV 的組合因其高效性、靈活性和跨平臺特性,成為許多開發者的首選。
本文將詳細介紹如何在 QtC++ 環境下,調用 tesseractOCR 引擎,并搭配 OpenCV 進行圖像處理,從而實現高效準確的文字識別功能。重點將圍繞 tesseract 的導入方法、核心接口以及在整個 OCR 流程中的作用展開。?
一、文字識別技術與工具鏈解析?
1.1 文字識別(OCR)的應用場景與技術難點?
文字識別,即 Optical Character Recognition,簡稱 OCR,是指通過電子設備(如掃描儀、相機等)將圖像中的文字轉換為可編輯的文本格式的技術。其應用場景極為廣泛:如電子文檔轉換,車牌識別系統的自動識別和管理;金融的票據識別提取支票、發票上的關鍵信息;翻譯類 APP 通過攝像頭識別外文并實時翻譯,極大地便利了人們的跨語言交流。?
然而,OCR 技術的實現并非易事,面臨著諸多技術難點。首先是圖像質量的影響,如模糊、傾斜、光照不均、存在噪聲等,都會導致文字識別準確率下降。其次,文字的字體、大小、顏色各異,以及可能存在的復雜背景,也會給識別帶來挑戰。此外,對于手寫體文字,由于其個性化強、規范性差,識別難度更大,所以這也是引入OpenCV來搭配處理圖像的主要原因。?
1.2 tesseract 與 OpenCV 在 OCR 中的角色?
tesseract 是一款開源的 OCR 引擎,由 Google 維護。它支持多種語言的文字識別,具有較高的識別準確率和良好的擴展性。tesseract 的核心作用是對經過預處理的圖像進行分析,提取其中的文字信息并轉換為文本。它可以處理不同字體、大小和格式的文字,并且能夠通過訓練來提高對特定場景文字的識別能力。?
OpenCV 是一個開源的計算機視覺庫,包含了大量的圖像處理和計算機視覺算法。在 OCR 流程中,OpenCV 主要負責圖像的預處理工作,如圖像的灰度化、二值化、降噪、傾斜校正等。通過這些預處理操作,可以改善圖像的質量,突出文字區域,為后續 tesseract 的文字識別創造良好的條件,從而提高整個 OCR 系統的識別準確率。?
1.3 協同工作的基本流程?
tesseract 和 OpenCV 協同實現文字識別的基本流程如下:?
首先,通過文件操作或攝像頭接口獲取需要識別的圖像文件或實時圖像。然后,將獲取到的圖像傳遞給 OpenCV 進行預處理,包括灰度化處理(將彩色圖像轉換為黑白圖像,減少計算量)、二值化處理(將圖像轉換為只有黑白兩種顏色,使文字與背景分離)、降噪處理(去除圖像中的噪聲點,避免干擾識別)、傾斜校正(將傾斜的文字圖像校正為水平狀態,便于 tesseract 識別)等。?
預處理完成后,將處理后的圖像數據傳遞給 tesseractOCR 引擎。tesseract 對圖像進行分析,識別出其中的文字,并將其轉換為文本信息。最后,將 tesseract 返回的文本信息進行展示、存儲或進一步處理,如通過 UI 界面顯示識別結果,或將結果保存到文件中。?
二、開發環境搭建?
2.1 OpenCV 的安裝與 Qt 配置?
OpenCV 的安裝步驟詳情可參考之前的文章,在此就簡單說下:?
- 從 OpenCV 官網(https://opencv.org/)下載對應操作系統的 OpenCV 安裝包,解壓到指定目錄。?或者自行編譯源碼得到。
- 配置 OpenCV 的環境變量,將 OpenCV 的 bin 目錄添加到系統的 PATH 環境變量中,這樣在運行程序時,系統能夠找到 OpenCV 的動態鏈接庫。?
- 在 Qt 項目中配置 OpenCV。打開 Qt Creator,創建一個新的 Qt 項目。然后在項目的.pro 文件中添加 OpenCV 的頭文件路徑和庫文件路徑。例如:
INCLUDEPATH += D:/opencv/build/include
LIBS += -LD:/opencv/build/x64/vc15/lib -lopencv_world455d.lib
其中,INCLUDEPATH 指定了 OpenCV 頭文件的所在目錄,LIBS 指定了 OpenCV 庫文件的所在目錄以及需要鏈接的庫文件。需要根據實際的 OpenCV 安裝路徑和版本進行修改。?
2.2 tesseract 的安裝與 Qt 配置?
tesseract 的安裝和配置相對復雜一些,具體步驟如下:?
- 下載 tesseract 安裝包。可以從 tesseract 的官方 GitHub 倉庫(https://github.com/tesseract-ocr/tesseract)下載源碼自行編譯,也可以下載別人編譯好的庫來用。對于 Windows 系統,注意別直接下載tesseract 的安裝包,里邊只有Dll沒有lib靜態庫,也沒有頭文件,只能拿他的測試程序來試試效果,沒法引入到代碼中調用。?
想要代碼調用的話,要么就直接下載源碼包,自己用CMake搭配VS進行編譯,要么就找別人編譯好的庫(包含動態庫,靜態庫,頭文件)。 - 安裝 tesseract 其實跟OpenCV一樣,就是將壓縮包或者編譯好的文件放置到指定目錄即可,然后將 tesseract 的安裝目錄添加到系統環境變量中。此外,還可以選擇安裝需要的語言數據包,如英文、中文等,這些語言數據包用于支持對應語言的文字識別。?
- 在 Qt 項目中配置 tesseract。首先,需要將 tesseract 的頭文件目錄和庫文件目錄添加到 Qt 項目的.pro 文件中。例如:
INCLUDEPATH += C:/Program Files/Tesseract-OCR/include
LIBS += -LC:/Program Files/Tesseract-OCR/lib \-ltesseract51.lib
除了在.pro 文件中配置,還需要將 tesseract 的動態鏈接庫(如 tesseract51.dll)復制到 Qt 項目的可執行文件所在目錄,否則程序運行時會出現找不到庫文件的錯誤。
三、tesseract 的深入解析?
3.1 tesseract 的特點?
tesseract 最初是由惠普公司開發的 OCR 引擎,后來被 Google 收購并開源。經過多年的發展和優化,tesseract 已經成為目前最受歡迎的開源 OCR 引擎之一。?
tesseract 具有以下特點:?
- 開源免費:可以自由使用和修改,無需支付任何費用,降低了開發成本。?
多語言支持:支持超過 100 種語言的文字識別,包括中文、英文、日文、韓文等,滿足不同場景的需求。? - 高識別準確率:在經過適當的圖像預處理和訓練后,tesseract 能夠達到較高的識別準確率,尤其是對于印刷體文字。?
- 跨平臺性:可以在 Windows、Linux、Mac 等多個操作系統上運行。?
- 可擴展性:支持用戶自定義訓練數據,以提高對特定字體、特定場景文字的識別能力。?
3.2 tesseract 的核心功能與工作原理?
tesseract 的核心功能是對圖像中的文字進行識別并轉換為文本。其工作原理主要包括以下幾個步驟:?
- 圖像預處理:tesseract 首先會對輸入的圖像進行一些基本的預處理,如二值化、去噪等,但這部分功能相對簡單,通常需要結合 OpenCV 進行更復雜的預處理。?
- 文字區域檢測:tesseract 會分析圖像,找出其中可能包含文字的區域。?
- 字符分割:將文字區域中的字符逐個分割出來,以便進行單獨識別。?
- 特征提取:對每個分割出來的字符提取特征,如形狀、輪廓、筆畫等。?
- 字符識別:將提取到的字符特征與訓練數據中的特征進行比對,從而識別出字符。?
- 文本輸出:將識別出的字符組合成文本,并輸出給用戶。?
3.3 tesseract 的主要接口及使用說明?
tesseract 提供了豐富的 C++ 接口,方便開發者進行調用。下面介紹一些主要的接口及其使用說明。?
- tesseract::TessBaseAPI類:這是 tesseract 的核心類,提供了文字識別的主要功能。?
構造函數:tesseract::TessBaseAPI(),創建一個 TessBaseAPI 對象。? - Init方法:用于初始化 tesseract 引擎。其原型為:
int Init(const char* datapath, const char* language, OcrEngineMode oem = OEM_DEFAULT);
其中,datapath是語言數據包所在的目錄,如果為 NULL,則使用默認目錄;language是要識別的語言,如 “eng” 表示英文,“chi_sim” 表示簡體中文;oem是 OCR 引擎模式,默認使用 OEM_DEFAULT。?
例如:
tesseract::TessBaseAPI tess;
if (tess.Init(NULL, "chi_sim+eng") != 0) {qDebug() << "無法初始化tesseract引擎!";return -1;
}
上述代碼就是初始化 tesseract 引擎,并設置支持簡體中文和英文識別。?
- SetImage方法:設置要識別的圖像。其原型有多種,常用的有:
void SetImage(const unsigned char* imagedata, int width, int height, int bytes_per_pixel, int bytes_per_line);
其中,imagedata是圖像數據的指針;width和height是圖像的寬度和高度;bytes_per_pixel是每個像素的字節數,如灰度圖像為 1,RGB 圖像為 3;bytes_per_line是每行圖像的字節數。?
調用方法如下(結合 OpenCV):
cv::Mat image = cv::imread("test.png");
if (image.empty()) {qDebug() << "無法讀取圖像!";return -1;
}
tess.SetImage(image.data, image.cols, image.rows, image.channels(), image.step);
代碼中將 OpenCV 讀取的圖像設置為 tesseract 要識別的圖像。?
- GetUTF8Text方法:獲取識別到的 UTF-8 編碼的文本。其原型為:
char* GetUTF8Text();
調用如下:
char* outText = tess.GetUTF8Text();
qDebug() << "識別結果:" << QString(outText);
delete[] outText; // 注意釋放內存
- End方法:釋放 tesseract 引擎占用的資源。其函數原型為:
void End();
在程序結束時,調用該方法釋放資源。?
- SetPageSegMode方法:設置頁面分割模式,用于指定 tesseract 如何分割圖像中的文字區域。例如:
tess.SetPageSegMode(tesseract::PSM_AUTO); // 自動頁面分割模式
- SetVariable方法:設置 tesseract 的一些變量參數,以調整識別效果。例如:
tess.SetVariable("tessedit_char_whitelist", "0123456789"); // 只識別數字
3.5 tesseract 在 OCR 流程中的作用?
tesseract 在整個 OCR 流程中扮演著最核心的文字識別角色。在經過 OpenCV 的圖像預處理后,圖像的質量得到了改善,文字區域更加突出。此時,tesseract 接收預處理后的圖像,通過其內部的一系列算法,對圖像中的文字進行分析和識別。?
它首先對圖像進行文字區域檢測,確定哪些部分包含文字;然后將文字區域分割成單個字符;接著提取每個字符的特征,并與訓練數據中的特征進行比對,從而識別出字符;最后將識別出的字符組合成完整的文本并輸出。?
可以說,tesseract 是 OCR 系統的 “大腦”,負責將圖像中的視覺信息轉換為文本信息,是實現文字識別功能的關鍵環節。?
四、OpenCV 圖像處理在 OCR 中的應用?
4.1 圖像預處理的重要性?
圖像預處理是 OCR 流程中至關重要的一步,其質量直接影響后續文字識別的準確率。原始圖像可能存在各種問題,如光照不均、噪聲干擾、圖像傾斜、文字與背景對比度低等,這些都會導致 tesseract 識別困難。通過圖像預處理,可以解決這些問題,改善圖像質量,使文字更加清晰、突出,從而提高 tesseract 的識別效率和準確率。?
4.2 OpenCV 的主要圖像處理功能?
OpenCV 提供了豐富的圖像處理函數,以下是在 OCR 中常用的一些功能:?
- 圖像讀取與保存:cv::imread函數用于讀取圖像,cv::imwrite函數用于保存圖像。
cv::Mat image = cv::imread("input.png"); // 讀取圖像
cv::imwrite("output.png", image); // 保存圖像
- 灰度化處理:將彩色圖像轉換為灰度圖像,減少圖像的通道數,降低計算量。cv::cvtColor函數可以實現這一功能。
cv::Mat grayImage;
cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY); // 將BGR彩色圖像轉換為灰度圖像
- 二值化處理:將灰度圖像轉換為二值圖像(只有黑白兩種顏色),使文字與背景分離。cv::threshold函數是常用的二值化函數。
cv::Mat binaryImage;
cv::threshold(grayImage, binaryImage, 127, 255, cv::THRESH_BINARY); // 簡單閾值二值化
其中,127 是閾值,大于閾值的像素被設置為 255(白色),小于等于閾值的像素被設置為 0(黑色)。?
- 降噪處理:去除圖像中的噪聲點,常用的方法有中值濾波、高斯濾波等。
cv::Mat denoisedImage;
cv::medianBlur(binaryImage, denoisedImage, 3); // 中值濾波,3是濾波器大小
- 傾斜校正:對于傾斜的文字圖像,需要進行校正,使其水平。可以通過霍夫變換檢測圖像中的線條,計算傾斜角度,然后進行旋轉校正。
cv::Mat edges;?
cv::Canny (denoisedImage, edges, 50, 150, 3); // 邊緣檢測?
cv::Mat lines;?
cv::HoughLinesP (edges, lines, 1, CV_PI / 180, 50, 50, 10); // 霍夫變換檢測直線?
double angle = 0;?
int count = 0;?
for (int i = 0; i < lines.rows; i++) {?
cv::Vec4i l = lines.atcv::Vec4i(i);?
double theta = atan2 (l [3] - l [1], l [2] - l [0]) * 180 / CV_PI;?
if (fabs (theta) < 45 && fabs (theta) > 5) { // 過濾接近水平或垂直的線?
angle += theta;?
count++;?
}?
}?
if (count > 0) {?
angle /= count; // 計算平均傾斜角度?
}?
cv::Point2f center((denoisedImage.cols - 1) / 2.0f, (denoisedImage.rows - 1) / 2.0f);?
cv::Mat rotMat = cv::getRotationMatrix2D(center, angle, 1.0);?
cv::Mat rotatedImage;?
cv::warpAffine(denoisedImage, rotatedImage, rotMat, denoisedImage.size(), cv::INTER_CUBIC, cv::BORDER_REPLICATE);
五、案例:構建一個簡單的 OCR 應用程序
5.1 應用程序功能如下:
實戰案例將構建一個簡單的 OCR 應用程序,具有以下功能:?
支持打開本地圖像文件(如 png、jpg、bmp 等格式)。?
對打開的圖像進行預處理(灰度化、二值化、降噪、傾斜校正等)。?
顯示原始圖像和預處理后的圖像。?
對預處理后的圖像進行文字識別,并顯示識別結果。?
支持將識別結果保存為文本文件。
5.2 代碼實現:
void MainWindow::on_btn1_clicked()
{// 1. 初始化 Tesseracttesseract::TessBaseAPI *ocrAPI = new tesseract::TessBaseAPI();// 語言包路徑(Windows 為安裝目錄下的 tessdata,Linux 可省略路徑)if (ocrAPI->Init(QString("D:/Tesseract_OCR/Tesseract_OCR5/tessdata").toStdString().c_str(), "chi_sim+eng")) {ui->textEdit->setText("初始化失敗!檢查語言包路徑");return;}// 2. 加載圖像(使用 OpenCV 讀取,轉為灰度圖優化識別)QString fileName = QFileDialog::getOpenFileName(this,QString("文件對話框"),"/",QString("圖片(*.jpg *.png);"));// 讀取圖像Mat img = imread(fileName.toStdString(), IMREAD_COLOR);if (img.empty()) {qDebug() << QString("無法讀取圖像!");return;}cv::cvtColor(img, img, cv::COLOR_BGR2GRAY); // 轉為灰度圖cv::threshold(img, img, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU); // 二值化// 3. 設置圖像并識別ocrAPI->SetImage(img.data, img.cols, img.rows, 1, img.step); // 單通道(灰度圖)ocrAPI->SetPageSegMode(tesseract::PSM_SINGLE_BLOCK); // 單塊文本模式// 4. 獲取識別結果char *outText = ocrAPI->GetUTF8Text();QString ocrResult(outText);ui->textEdit->setText(QString("識別結果:\n%1").arg(ocrResult));// 5. 釋放資源delete[] outText;ocrAPI->End();delete ocrAPI;
}
以上即是使用tesseract 開源庫實現OCR文字識別的一個基本應用。