opencv实践-OCR识别c++版

38 篇文章 1 订阅

1. OCR 简介

OCR (Optical Character Recognition,光学字符识别)是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,通过检测暗、亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程;即,针对印刷体字符,采用光学的方式将纸质文档中的文字转换成为黑白点阵的图像文件,并通过识别软件将图像中的文字转换成文本格式,供文字处理软件进一步编辑加工的技术。如何除错或利用辅助信息提高识别正确率,是OCR最重要的课题,ICR(Intelligent Character Recognition)的名词也因此而产生。衡量一个OCR系统性能好坏的主要指标有:拒识率、误识率、识别速度、用户界面的友好性,产品的稳定性,易用性及可行性等。

2. 实现步骤

  • 灰度化处理:
  • 采用高斯滤波去噪
  • 边缘检测
  • 查找轮廓并排序:
  • 绘制全部轮廓
  • 多边形逼近
  • 仿射变换
  • 写入图片文件
  • 扫描读取
  • 写入本地

3. 代码实现

识别图片:
在这里插入图片描述
源码:

#include <opencv2/opencv.hpp>
#include <vector>
#include <map>
#include <string>
#include "tesseract/baseapi.h"
#include "leptonica\allheaders.h"

using namespace cv;
using namespace std;

void order_point(const std::vector<cv::Point>& inPots, std::vector<cv::Point>& outPots)
{
	// 左上的坐标一定是x, y加起来最小的坐标.
	// 右下的坐标一定是x, y加起来最大的坐标.
	// 右上角的x, y相减的差值一定是最小的.
	// 左下角的x, y相减的差值, 一定是最大.
	// diff的作用是后一列减前一列得到的差值 y - x
	int index = 0;
	map<int, int> sum_dict;
	map<int, int> diff_dict;
	for (auto& p : inPots)
	{
		int sum = p.x + p.y;
		int diff = p.y - p.x;
		sum_dict.insert(std::make_pair(sum, index));
		diff_dict.insert(std::make_pair(diff, index));
		index++;
	}
	outPots[0] = inPots.at(sum_dict.begin()->second);
	outPots[1] = inPots.at(diff_dict.begin()->second);
	outPots[2] = inPots.at(sum_dict.rbegin()->second);
	outPots[3] = inPots.at(diff_dict.rbegin()->second);
}

cv::Mat four_point_transform(const cv::Mat &image, const std::vector<cv::Point> &pts)
{
	std::vector<cv::Point> rect(4);
	order_point(pts, rect);
	cv::Point lt, rt, rb, lb;
	lt = rect.at(0);
	rt = rect.at(1);
	rb = rect.at(2);
	lb = rect.at(3);

	//空间中两点的距离,并且要取最大的距离确保全部文字都看得到
	int widthA = sqrt(pow((rb.x - lb.x), 2) + pow((rb.y - lb.y), 2));
	int widthB = sqrt(pow((rt.x - lt.x), 2) + pow((rt.y - lt.y), 2));
	int max_width = max(widthA, widthB);

	int heightA = sqrt(pow((rt.x - rb.x), 2) + pow((rt.y - rb.y), 2));
	int heightB = sqrt(pow((lt.x - lb.x), 2) + pow((lt.y - lb.y), 2));
	int max_height = max(heightA, heightB);

	//计算变换矩阵
	Point2f AffinePoints0[4] = { Point2f(lt.x, lt.y), Point2f(rt.x, rt.y), Point2f(rb.x, rb.y), Point2f(lb.x, lb.y) };
	Point2f AffinePoints1[4] = { Point2f(0, 0), Point2f(max_width, 0), Point2f(max_width, max_height), Point2f(0, max_height) };

	Mat Trans = cv::getPerspectiveTransform(AffinePoints0, AffinePoints1);
	cv::Mat dst;
	cv::warpPerspective(image, dst, Trans, Size(max_width, max_height), INTER_CUBIC);

	return dst;
}

cv::Mat Image_Pretreatment(cv::Mat image)
{
	// 计算比例.限定高度500
	// 此时像素点都缩小了一定的比例,进行放射变换时要还原
	float ratio = image.rows / 500.0;
	// 拷贝一份
	cv::Mat image_copy = image.clone();
	// 修改尺寸
	cv::resize(image_copy, image, cv::Size(image.cols / ratio, 500));
	//cv::imshow("image", image);
	// 图片预处理
	
	// 灰度化处理
	cv::Mat gray, Gaussian, edged;
	cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
	//cv::imshow("gray", gray);
	// 高斯平滑
	cv::GaussianBlur(gray, Gaussian, Size(5, 5), 0);
	// cv_show('Gaussian', Gaussian)
	// 边缘检测,寻找边界(为后续查找轮廓做准备)
	cv::Canny(Gaussian, edged, 70, 200);
	//cv::imshow("edged", edged);
	// 查找轮廓
	std::vector<std::vector<cv::Point>> cnts;
	cv::findContours(edged, cnts, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
	// 将轮廓按照面积降序排序
	sort(cnts.begin(), cnts.end(), [&](std::vector<cv::Point> &v1, std::vector<cv::Point> &v2) {
		return cv::contourArea(v1) > cv::contourArea(v2);
		});
	
	// 绘制所有轮廓
	cv::Mat image_contours = image.clone();
	cv::drawContours(image_contours, cnts, -1, (0, 0, 255), 1);
	//cv::imshow("image_contours", image_contours);
	image_contours.release();

	vector<cv::Point> screen_cnt;
	// 遍历轮廓找出最大的轮廓.
	for (auto& c : cnts) {
		// 计算轮廓周长
		int perimeter = cv::arcLength(c, true);
		// 多边形逼近,得到近似的轮廓
		// 近似完后,只剩下四个顶点的角的坐标
		vector<cv::Point> approx(c.size());
		cv::approxPolyDP(c, approx, 0.02 * perimeter, true);
		// 最大的轮廓
		if (approx.size() == 4) {
			// 接收approx
			screen_cnt = approx;
			break;
		}
	}
	// 画出多边形逼近
	cv::Mat image_screen_cnt = image.clone();
	cv::drawContours(image_screen_cnt, std::vector< vector<cv::Point>>{screen_cnt}, -1, (0, 0, 255), 1);
	//cv::imshow("image_screen_cnt", image_screen_cnt);
	image_screen_cnt.release();
	// 进行仿射变换,使图片变正
	for (auto& scr_t : screen_cnt)
	{
		scr_t.x *= ratio;
		scr_t.y *= ratio;
	}
	cv::Mat warped = four_point_transform(image_copy, screen_cnt);
	//cv::imshow("warped", warped);
	// 二值处理,先转成灰度图
	cv::Mat warped_gray;
	cv::cvtColor(warped, warped_gray, cv::COLOR_BGR2GRAY);
	// 再二值化处理
	cv::Mat ref;
	cv::threshold(warped_gray, ref, 150, 255, cv::THRESH_BINARY);
	//cv::namedWindow("ref", WINDOW_NORMAL);
	//cv::imshow("ref", ref);
	//cv::waitKey(0);

	return ref;
}

int main()//ocr_demo()
{
	// 读取图片
	cv::Mat image = cv::imread("C:\\Users\\Administrator\\Desktop\\1.jpg");
	
	// 返回透视变换的结果
	cv::Mat ref = Image_Pretreatment(image);
	// 把处理好的图片写入图片文件.
	cv::imwrite("ref.jpg", ref);
	
	char* outText;
	// Open input image with leptonica library
	Pix* img_pix = pixRead("ref.jpg");
	api->SetImage(img_pix);
	// Get OCR result
	outText = api->GetUTF8Text();
	printf("OCR output:\n%s", outText);

	// Destroy used object and release memory
	api->End();
	delete api;
	delete[] outText;
	pixDestroy(&img_pix);

	return 0;
}

4. 待完成

上述代码中的ocr识别部分,由于tesseract库一直没调通,因此没做验证,后期会补上。

本文参考:
https://blog.csdn.net/weixin_56197703/article/details/124309367

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
### 回答1: OCR(Optical Character Recognition,光学字符识别)是一种将印刷体字符转换成机器可编辑文本形式的技术。OCR 文字识别源码指的是用于实现 OCR 功能的程序代码。以下是一个关于 C 语言实现 OCR 文字识别的简要说明。 首先,C 语言是一种广泛应用于系统开发的编程语言,它拥有高效性、跨平台性以及强大的底层控制能力,适合用于编写源代码。要实现 OCR 文字识别功能,我们可以使用 C 语言结合相关的图像处理库或者人工智能库。 在实现 OCR 文字识别功能时,主要的步骤包括图像预处理、字符分割和字符识别。首先,需要将待识别的图像进行预处理,例如灰度化、二值化、噪声去除、图像增强等操作,以提高字符区域的清晰度和可识别性。然后,对预处理后的图像进行字符分割,将每个字符从图像中分割出来,形成单独的字符图像。最后,借助机器学习和模式识别算法,通过训练模型将字符图像与对应的字符进行匹配,实现字符识别的功能。 在进行图像预处理、字符分割和字符识别时,我们可以使用一些开源的图像处理库和机器学习库,例如OpenCV、Tesseract等,它们提供了一系列的函数和算法,可用于图像处理和特征提取。同时,我们可以根据具体需求选择适合的机器学习算法,如神经网络、支持向量机、决策树等,以实现准确的字符识别效果。 综上所述,实现 OCR 文字识别源码需要结合 C 语言和相关的图像处理库和机器学习库,通过图像预处理、字符分割和字符识别等步骤,可以实现将印刷体字符转换成可编辑文本的功能。 ### 回答2: OCR(Optical Character Recognition,光学字符识别)是一种将图片或扫描的文本转化为可编辑、可搜索的电子文本的技术。OCR 文字识别源码是指实现这种技术的程序代码。 OCR 文字识别源码通常基于计算机视觉和机器学习算法。它通过分析图像的像素构成和排列方式,将文字的形状、大小以及位置等特征提取出来。然后,通过匹配这些特征与已知字符的特征,识别出输入图像中的文字。 一个完整的 OCR 文字识别源码需要包括以下几个关键步骤: 1. 图像预处理:对输入的图像进行去噪、灰度化、二值化等处理,将图像转化为更适合字符分析的形式。 2. 字符分割:将处理后的图像中的字符分割出来,以便逐个识别。 3. 特征提取:对每个分割出来的字符提取其独特的特征,如轮廓、颜色等。 4. 字符识别:将提取出的特征与已知字符的特征进行匹配,以识别出输入图像中的字符。 5. 结果输出:将识别结果输出为可编辑或可搜索的文本格式。 当然,实现一个准确、高效的 OCR 文字识别源码并不简单,因为面临着多种挑战,如图像质量、字符字体和大小变化、文字横向倾斜等。因此,开发者需要综合运用图像处理、模式识别、机器学习等领域的知识来提高准确率和性能。 目前,已经有一些开源的OCR文字识别源码可供使用,如Google的Tesseract OCROpenCV等。开发者可以借助这些源码,快速实现自己的OCR文字识别应用,如扫描文档的文字提取、车牌识别等。 总之,OCR 文字识别源码是实现文字识别技术的程序代码,通过图像处理和机器学习算法,能够将图像中的文字转化为可编辑、可搜索的文本。开发者可以借助现有的开源源码来实现自己的OCR文字识别应用。 ### 回答3: OCR(Optical Character Recognition,光学字符识别)是一种将印刷文字转换为可编辑电子文档的技术。OCR 文字识别源码是指用于实现OCR技术的程序代码。 源码通常由一系列算法和模型构成,用于识别并提取图像中的文字内容。OCR源码的实现过程包括以下几个关键步骤: 1. 图像预处理:对待处理图像进行灰度化、二值化、降噪等操作,以便更好地提取文字。 2. 文字定位:通过图像处理技术找到图像中的文字区域,确定文字的相对位置。 3. 字符分割:对文字区域进行切割,将整个文字区域切割成单个字符的图像。 4. 特征提取:对每个字符的图像进行特征提取,并将其转换为计算机可以理解的数字表示形式。 5. 文字识别:利用训练好的OCR模型,对提取出的字符特征进行识别,得到最终的文本结果。 常见的OCR文字识别源码有Tesseract、OpenCV、Pytesseract等。这些源码开源且广泛使用,可以根据实际需求进行自定义修改和优化。 OCR文字识别源码在很多领域有广泛应用,如数字化档案管理、自动车牌识别、印刷品扫描等。通过将图像中的文字转换为可编辑的文本,极大地提高了文字信息的利用效率和便捷程度。 当然,OCR技术也面临一些挑战,如字体、字号、倾斜度、光照条件等因素的影响,可能会降低识别的准确性。因此,在实际应用中,可能需要进一步优化和调整OCR源码,以提高识别的精度和稳定性。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值