基础入门
文字识别技术,也称为光学字符识别(Optical Character Recognition,OCR),是一种让计算机能够“读取”图像中的文字,并将其转化为可编辑文本的技术。这项技术在许多领域都有广泛的应用,包括但不限于:图片文字识别、文档管理、自动化数据输入、历史文献数字化。
文字识别通常包含以下6个主要步骤。
1、图像预处理:包括图像的读取、灰度化、二值化、去噪等。
2、文本区域检测:定位图像中的文本区域。
3、字符分割:将文本区域分割成单个字符。
4、特征提取:提取字符的特征,用于后续识别。
5、字符识别:通过机器学习模型或其他技术识别字符。
6、后处理:校正识别结果,优化输出。
OpenCV本身并没有内置的文字识别功能,但它可以与其他OCR工具(比如:Tesseract OCR)集成,或将提取的特征用于训练深度学习模型(比如:CRNN)以进行识别。在OpenCV中使用CRNN进行文字识别,与前面介绍的目标检测基本差不多,都是使用cv::dnn来进行推理,故下面着重介绍Tesseract OCR。
Tesseract OCR
Tesseract OCR是一款开源的光学字符识别工具,它能够将图像中的文字转换为可编辑的文本。Tesseract是目前最先进和广泛使用的OCR引擎之一,支持多种语言,并且具有很高的识别准确率。Tesseract OCR最初是由HP(惠普)公司于1980年开发的,后来由Google接手维护和发展。自2006年以来,Google一直在支持Tesseract的开发,并将其开源,使之成为了一个社区驱动的项目。
Tesseract OCR具有以下几个主要特点。
开源:Tesseract是完全免费的,并且它的源代码是开放的,任何人都可以查看、修改和分发。
多平台支持:支持Windows、Linux、MacOS等多种操作系统。
多语言支持:支持多种语言,包括英语、中文、日语、韩语等超过100种语言。
高准确率:Tesseract在识别印刷文本方面表现出色,并且对于某些语言的手写识别也有较好的效果。
灵活的接口:Tesseract提供了多种编程语言的接口,包括C/C++、Python等,方便开发者集成到自己的应用程序中。
可以在https://github.com/UB-Mannheim/tesseract/wiki下载Tesseract OCR的Windows安装包,当前最新版本为5.4.0。
安装时,可以选择下载中文的训练包。这样,进行文字识别时,才可以识别出中文。使用Tesseract的常用命令如下。
// 输出tesseract的版本信息
tesseract.exe --version// 列出所有支持的语言包
tesseract.exe --list-langs// 从图片中识别文字,将结果输出到文本文件中
tesseract.exe G:\\1.png G:\\output -l chi_sim
如果要在OpenCV中集成Tesseract OCR进行开发,则需要下载Tesseract OCR的源码。由于Tesseract OCR依赖Leptonica库,故还需要下载Leptonica库的源码。我们可以使用CMake来编译Tesseract OCR,最终得到编译好的库和头文件。
Tesseract OCR的核心类是TessBaseAPI,它提供了初始化、设置图像、获取识别结果等一系列功能。主要的一些接口如下。
Init:初始化Tesseract引擎。
SetImage:设置要识别的图像。
GetUTF8Text:获取识别后的UTF-8编码的文本。
End:结束并释放资源。
实战解析
在下面的实战代码中,我们首先通过OpenCV读取了一个带文字的图片文件(见下图),并将其转换为灰度图以提高OCR的识别准确性。接着,我们初始化了Tesseract OCR引擎,指定了语言为简体中文,并使用默认的OCR引擎模式。
为了使Tesseract能够处理图像,我们通过自定义的Mat8ToPix函数将OpenCV的Mat对象转换为Leptonica库的PIX对象。然后,将转换后的PIX对象作为OCR引擎的输入图像。最后,我们执行OCR识别操作,获取到识别结果。该结果是以UTF-8编码的字符串形式存储的,需要转换为ANSI字符集来显示。注意:GetUTF8Text返回的字符串,必须使用delete []的形式进行释放,否则会导致内存泄漏。
#include <opencv2/opencv.hpp>
using namespace cv;#include <iostream>
using namespace std;#include <tesseract/baseapi.h>
using namespace tesseract;#include <leptonica/allheaders.h>Pix *Mat8ToPix(cv::Mat *pMat)
{Pix *pPix = pixCreate(pMat->size().width, pMat->size().height, 8);for(int y = 0; y < pMat->rows; y++){for(int x = 0; x <pMat->cols; x++){pixSetPixel(pPix, x, y, (l_uint32)pMat->at<uchar>(y, x));}}return pPix;
}string Utf8ToAnsi(const string& utf8Str)
{int wideLen = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, NULL, 0);wstring wideStr(wideLen, L'\0');MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, &wideStr[0], wideLen);int ansiLen = WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), -1, NULL, 0, NULL, NULL);string ansiStr(ansiLen, '\0');WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), -1, &ansiStr[0], ansiLen, NULL, NULL);return ansiStr;
}int main(int argc, char **argv)
{Mat image = imread("Text.png");if (image.empty()){cout << "Can not open or find the image" << endl;return -1;}Mat grayImage;cvtColor(image, grayImage, COLOR_BGR2GRAY);// 初始化Tesseract引擎TessBaseAPI *pTess = new TessBaseAPI();// chi_sim表示简体中文if (pTess->Init("C:\\Program Files\\Tesseract-OCR\\tessdata", "chi_sim", OEM_DEFAULT)){cout << "Can not initialize tesseract." << endl;return -1;}// 将OpenCV图像转换为Leptonica的PIX对象PIX *pPix = Mat8ToPix(&grayImage);// 设置图像源pTess->SetImage(pPix);// 进行OCR识别char *pszText = pTess->GetUTF8Text();string strResult = Utf8ToAnsi(pszText);// 输出识别结果cout << "Text: [" << strResult << "]" << endl;delete[] pszText;pTess->End();delete pTess;pixDestroy(&pPix);return 0;
}
执行上面的代码,运行效果可参考下图。