OpenCV C++案例实战三十二《字符识别》

这篇具有很好参考价值的文章主要介绍了OpenCV C++案例实战三十二《字符识别》。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

本案例将使用OpenCV C++ 进行字符识别。主要包括制作数据集、以及模型预测两部分。先看看效果如何吧。

一、结果演示

c++ 图片文字识别,OpenCV C++项目实战,opencv,c++,计算机视觉

二、制作数据集

首先第一步,我们需要制作数据集。这里我的方法是,读取一张字符图像,然后通过提取字符轮廓找到字符ROI图像,利用键盘输入给字符打上相应的标签,即完成数据集制作。由于我这里的数据字符图像只包含数字以及大写英文字符,故只识别数字字符以及大写英文字符。如图所示,这是我使用的字符图像,下面需要进行图像预处理提取到字符轮廓。
c++ 图片文字识别,OpenCV C++项目实战,opencv,c++,计算机视觉

//进行图像预处理,提取字符轮廓
Mat grayImg;
cvtColor(Train_Chars, grayImg, COLOR_BGR2GRAY);

Mat blurImg;
GaussianBlur(grayImg, blurImg, Size(3, 3), 0);

Mat binImg;
threshold(blurImg, binImg, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);

c++ 图片文字识别,OpenCV C++项目实战,opencv,c++,计算机视觉
接下来需要提取字符轮廓,使用findContours提取最外轮廓。然后提取字符ROI图像,并通过键盘输入对应的ASCII码给其打上标签(注:区分大小写)。
c++ 图片文字识别,OpenCV C++项目实战,opencv,c++,计算机视觉

Rect rect = boundingRect(contours[cnt]);
rectangle(Train_Chars, rect, Scalar(0, 255, 0), 2);

Mat ROI = binImg(rect);
imshow("ROI", ROI);
imshow("Training_Chars", Train_Chars);
int charVal = waitKey(0); //将字符通过键盘输入给予标签

进行KNN训练,具体看源码相应注释。

	//由于我这里的数据字符图像只包含数字以及大写英文字符,只识别数字字符以及大写英文字符
	vector<int>ValidChars =
	{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
	'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
	'U', 'V', 'W', 'X', 'Y', 'Z' };

	//进行图像预处理,提取字符轮廓
	Mat grayImg;
	cvtColor(Train_Chars, grayImg, COLOR_BGR2GRAY);

	Mat blurImg;
	GaussianBlur(grayImg, blurImg, Size(3, 3), 0);

	Mat binImg;
	threshold(blurImg, binImg, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
	imwrite("result.jpg", binImg);

	vector<vector<Point>>contours;
	findContours(binImg, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

	//准备训练所用数据集,将字符通过键盘输入给予标签
	Mat Train_Data, Train_Label;
	for (int cnt = 0; cnt < contours.size(); cnt++)
	{
		if (contourArea(contours[cnt]) > 10)
		{
			Rect rect = boundingRect(contours[cnt]);
			rectangle(Train_Chars, rect, Scalar(0, 255, 0), 2);

			Mat ROI = binImg(rect);
			imshow("ROI", ROI);
			imshow("Training_Chars", Train_Chars);
			int charVal = waitKey(0); //将字符通过键盘输入给予标签

			if (find(ValidChars.begin(), ValidChars.end(), charVal) != ValidChars.end())
			{
				//如果输入的字符在字符匹配表中,则进行存储
				
				//由于我们在识别字符时,会遇到各种尺寸的字符,故将所有的字符固定同一尺寸
				Mat resizeRoi;
				resize(ROI, resizeRoi, Size(ImgWidth, ImgHeight));

				//将图像转成浮点型,因为KNN训练数据集读取的是浮点型数据
				Mat RoiFloat;
				resizeRoi.convertTo(RoiFloat, CV_32FC1);

				Train_Data.push_back(RoiFloat.reshape(0,1));
				Train_Label.push_back(charVal);
				cout << charVal << endl;
			}
		}
	}

	//进行KNN训练
	Train_Data.convertTo(Train_Data, CV_32FC1);
	Train_Label.convertTo(Train_Label, CV_32FC1);
	const int k = 3;//k取值,基数
	Ptr<ml::KNearest>knn = ml::KNearest::create();//构造KNN模型
	knn->setDefaultK(k);//设定k值
	knn->setIsClassifier(true);//KNN算法可用于分类,回归
	knn->setAlgorithmType(ml::KNearest::BRUTE_FORCE);//字符匹配算法
	knn->train(Train_Data, ml::ROW_SAMPLE, Train_Label);//模型训练
	knn->save(filename);//模型保存

	cout << "Model training is complete!" << endl;

三、字符识别

当我们完成训练后,会保存相应的模型。这时我们仅需直接读取模型数据就可以了。

	Ptr<ml::KNearest>knn = cv::Algorithm::load<cv::ml::KNearest>(filename);//加载KNN模型

	//图像预处理
	Mat grayImg;
	cvtColor(Test_Chars, grayImg, COLOR_BGR2GRAY);

	Mat blurImg;
	GaussianBlur(grayImg, blurImg, Size(3, 3), 0);

	Mat binImg;
	threshold(blurImg, binImg, 200, 255, THRESH_BINARY_INV);

	vector<vector<Point>>contours;
	findContours(binImg, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);//查找最外轮廓
	for (int cnt = 0; cnt < contours.size(); cnt++)
	{
		if (contourArea(contours[cnt]) > 10)
		{
			Rect rect = boundingRect(contours[cnt]);//轮廓外接矩形
			rectangle(Test_Chars, rect, Scalar(0, 0, 255), 2);

			Mat ROI = binImg(rect);//字符ROI图像

			Mat resizeRoi;//将字符resize成固定大小
			resize(ROI, resizeRoi, Size(ImgWidth, ImgHeight));

			Mat RoiFloat;//将图像转化成CV_32FC1
			resizeRoi.convertTo(RoiFloat, CV_32FC1);
			RoiFloat = RoiFloat.reshape(0, 1);

			float f = knn->predict(RoiFloat);//进行字符识别预测

			//结果显示
			char text[50];
			sprintf_s(text, "%c",char(int(f)));
			cout << char(int(f)) << endl;//将字符结果float转成char
			double scale = rect.width * 0.02;
			putText(Test_Chars, text, rect.br(), FONT_HERSHEY_SIMPLEX, scale, Scalar(0, 255, 0), 2);
			imshow("Test_Chars", Test_Chars);
			waitKey(0); 

		}
	}

四、源码

#include<iostream>
#include<opencv2/opencv.hpp>
#include<opencv2/ml.hpp>
#include<fstream>
using namespace std;
using namespace cv;

const int ImgWidth = 20;//图片宽
const int ImgHeight = 30;//图片高

int main()
{
	//准备数据集
	Mat Train_Chars = imread("training_chars.png");//数据集图像
	Mat Test_Chars = imread("test.jpg");//测试图像
	if (Train_Chars.empty()|| Test_Chars.empty())
	{
		cout << "can not read the image..." << endl;
		system("pause");
		return -1;
	}

	string filename = "model.xml";//模型文件
	fstream fin;
	fin.open(filename, ios::in);
	if (fin.is_open())
	{
		Ptr<ml::KNearest>knn = cv::Algorithm::load<cv::ml::KNearest>(filename);//加载KNN模型

		//图像预处理
		Mat grayImg;
		cvtColor(Test_Chars, grayImg, COLOR_BGR2GRAY);

		Mat blurImg;
		GaussianBlur(grayImg, blurImg, Size(3, 3), 0);

		Mat binImg;
		threshold(blurImg, binImg, 200, 255, THRESH_BINARY_INV);

		vector<vector<Point>>contours;
		findContours(binImg, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);//查找最外轮廓
		for (int cnt = 0; cnt < contours.size(); cnt++)
		{
			if (contourArea(contours[cnt]) > 10)
			{
				Rect rect = boundingRect(contours[cnt]);//轮廓外接矩形
				rectangle(Test_Chars, rect, Scalar(0, 0, 255), 2);

				Mat ROI = binImg(rect);//字符ROI图像

				Mat resizeRoi;//将字符resize成固定大小
				resize(ROI, resizeRoi, Size(ImgWidth, ImgHeight));

				Mat RoiFloat;//将图像转化成CV_32FC1
				resizeRoi.convertTo(RoiFloat, CV_32FC1);
				RoiFloat = RoiFloat.reshape(0, 1);

				float f = knn->predict(RoiFloat);//进行字符识别预测

				//结果显示
				char text[50];
				sprintf_s(text, "%c",char(int(f)));
				cout << char(int(f)) << " ";//将字符结果float转成char
				double scale = rect.width * 0.02;
				putText(Test_Chars, text, rect.br(), FONT_HERSHEY_SIMPLEX, scale, Scalar(0, 255, 0), 2);
				imshow("Test_Chars", Test_Chars);
				waitKey(0); 

			}
		}
		cout << endl;
	}
	else
	{
		//由于我这里的数据字符图像只包含数字以及大写英文字符,只识别数字字符以及大写英文字符
		vector<int>ValidChars =
		{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
		'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
		'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
		'U', 'V', 'W', 'X', 'Y', 'Z' };

		//进行图像预处理,提取字符轮廓
		Mat grayImg;
		cvtColor(Train_Chars, grayImg, COLOR_BGR2GRAY);

		Mat blurImg;
		GaussianBlur(grayImg, blurImg, Size(3, 3), 0);

		Mat binImg;
		threshold(blurImg, binImg, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);

		vector<vector<Point>>contours;
		findContours(binImg, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

		//准备训练所用数据集,将字符通过键盘输入给予标签
		Mat Train_Data, Train_Label;
		for (int cnt = 0; cnt < contours.size(); cnt++)
		{
			if (contourArea(contours[cnt]) > 10)
			{
				Rect rect = boundingRect(contours[cnt]);
				rectangle(Train_Chars, rect, Scalar(0, 255, 0), 2);

				Mat ROI = binImg(rect);
				imshow("ROI", ROI);
				imshow("Training_Chars", Train_Chars);
				int charVal = waitKey(0); //将字符通过键盘输入给予标签

				if (find(ValidChars.begin(), ValidChars.end(), charVal) != ValidChars.end())
				{
					//如果输入的字符在字符匹配表中,则进行存储
					
					//由于我们在识别字符时,会遇到各种尺寸的字符,故将所有的字符固定同一尺寸
					Mat resizeRoi;
					resize(ROI, resizeRoi, Size(ImgWidth, ImgHeight));

					//将图像转成浮点型,因为KNN训练数据集读取的是浮点型数据
					Mat RoiFloat;
					resizeRoi.convertTo(RoiFloat, CV_32FC1);

					Train_Data.push_back(RoiFloat.reshape(0,1));
					Train_Label.push_back(charVal);
					cout << charVal << endl;
				}
			}
		}

		//进行KNN训练
		Train_Data.convertTo(Train_Data, CV_32FC1);
		Train_Label.convertTo(Train_Label, CV_32FC1);
		const int k = 3;//k取值,基数
		Ptr<ml::KNearest>knn = ml::KNearest::create();//构造KNN模型
		knn->setDefaultK(k);//设定k值
		knn->setIsClassifier(true);//KNN算法可用于分类,回归
		knn->setAlgorithmType(ml::KNearest::BRUTE_FORCE);//字符匹配算法
		knn->train(Train_Data, ml::ROW_SAMPLE, Train_Label);//模型训练
		knn->save(filename);//模型保存

		cout << "Model training is complete!" << endl;
	}

	destroyAllWindows();
	system("pause");
	return 0;
}

总结

本文使用OpenCV C++ 进行字符识别,主要操作有以下几点。
1、制作数据集,利用键盘输入字符相应的ASCII码
2、进行KNN训练,得到训练模型
3、将预测结果转回相应的字符char类型文章来源地址https://www.toymoban.com/news/detail-598667.html

到了这里,关于OpenCV C++案例实战三十二《字符识别》的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++入门学习(十二)字符串类型

    上一节(C++入门学习(十一)字符型-CSDN博客)中我们学到如何表示和使用一个字符串,本篇文章是字符串(多个字符)。 定义字符串主要有两种方式: 第一种: char str[] = \\\"win\\\";  //char 变量名[] = \\\"字符串\\\" 第二种: #include string string str1 = \\\"winner\\\"; / / 两种方式代码:  注意字符

    2024年01月23日
    浏览(30)
  • OPENCV C++(十二)模板匹配

    正常模板匹配函数  这里0代表的是方法,一般默认为0就ok  img是输入图像 templatee是模板 resultmat是输出 对于输出的说明: 就是说result图像中的每一个点的值代表了一次相似度比较结果。  如图可知,模板在待测图像上每次在横向或是纵向上移动一个像素,并作一次比较计算

    2024年02月13日
    浏览(29)
  • opencv 案例实战01-停车场车牌识别实战

    车牌识别技术主要应用领域有停车场收费管理,交通流量控制指标测量,车辆定位,汽车防盗,高速公路超速自动化监管、闯红灯电子警察、公路收费站等等功能。对于维护交通安全和城市治安,防止交通堵塞,实现交通自动化管理有着现实的意义。 车牌自动识别系统应用的

    2024年02月11日
    浏览(29)
  • OpenCV(三十二):轮廓检测

    1.轮廓概念介绍         在计算机视觉和图像处理领域中,轮廓是指在图像中表示对象边界的连续曲线。它是由一系列相邻的点构成的,这些点在边界上连接起来形成一个封闭的路径。 轮廓层级:        轮廓层级(Contour Hierarchy)是指在包含多个轮廓的图像中,轮廓之间的

    2024年02月07日
    浏览(40)
  • Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之六 简单进行人脸训练与识别

    目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之六 简单进行人脸训练与识别 一、简单介绍 二、简单进行人脸训练与识别 1、LBPH(Local Binary Patterns Histograms)算法进行人脸训练和识别 2、实现步骤: 3、判断是谁的人脸: 案例中涉及的关键函数说

    2024年04月26日
    浏览(63)
  • Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之四 简单行人人体检测效果

    目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之四 简单行人人体检测效果 一、简单介绍 二、简单行人人体检测效果实现原理 三、简单行人人体检测效果案例实现简单步骤 四、注意事项 Python是一种跨平台的计算机程序设计语言。是一种面向对

    2024年04月26日
    浏览(36)
  • opencv 案例实战02-停车场车牌识别SVM模型训练及验证

    1. 整个识别的流程图: 2. 车牌定位中分割流程图: 三、车牌识别中字符分割流程图: 下载车牌相关字符样本用于训练和测试,本文使用14个汉字样本和34个数字跟字母样本,每个字符样本数为40,样本尺寸为28*28。 数据集下载地址 https://download.csdn.net/download/hai411741962/88248392

    2024年02月11日
    浏览(28)
  • 图像识别技术OpenCV | C++版本

    图像与信号 图像 图像是人对视觉感知的物质再现。图像可以由光学设备获取,也可以人为创作。随着数字采集技术和信号处理理论的发展,越来越多的图像以数字形式存储。因而,有些情况下”图像“一词实际上是指数字图像。图像相关的话题包括图像采集、图像制作、图

    2024年02月05日
    浏览(23)
  • opencv实现人脸识别(c++实现)

    本文章基于opencv + VS2015 实现人脸检测 可以直接打开摄像头对人脸进行识别,这些标识框也会跟随你的人脸移动。隐私问题,我这里对图片进行了识别。 opencv中文文档 官方文档说明 功能 :用于从视频文件、图像序列或摄像机捕获视频的类 3.1.1 open bool cv::VideoCapture::open(int i

    2024年02月07日
    浏览(38)
  • opencv C++ 识别照片中的人脸

    //识别照片中的人脸

    2024年02月11日
    浏览(22)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包