opencv——基于KNN的数字识别

本文介绍了一种使用KNN算法进行数字识别的方法,通过计算图片之间的相似度,选取K个最相似的图片来判断未知图片的类别。文章详细描述了如何准备训练样本,包括图像预处理、特征提取和数据格式转换,以及如何使用OpenCV和C++实现KNN训练和预测过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

KNN即K个最近邻,网上有很多关于KNN的文章。我大概总结下核心:假设有A图片,让A与训练样本依次计算相似度(可用欧式距离),挑选出K个与A图片相似度最大的图片,这K个图片中,哪种类型最多那么定义A图片也属于该类型。

首先,需要有数字的训练样本

https://download.youkuaiyun.com/download/weixin_41721222/10784418

 

KNN的数字识别代码与基于SVM的数字识别大体一致

https://blog.youkuaiyun.com/weixin_41721222/article/details/84953788

核心思路:

1:获取一张训练图片后会将图片特征写入到容器中,紧接着会将标签写入另一个容器中,这样就保证了特征和标签是一一对应的关系。

2:特征可用LBP,HOG等提取,但是我们这里主要说KNN训练过程,所以用最简单的方法,即把训练图片的全部像素序列成一行像素作为特征,用reshape(1,1)。

3:图片特征数据得转换成CV_32FC1的数据格式。

4:所有训练样本与测试样本的尺寸都应该一样(这里我都选择20*20)。

下面代码是opencv3和C++

可以根据自己需要修改训练样本类别,数目,尺寸。oss的训练样本路径,src的检测图片路径。

 

/// 字符识别——基于模版匹配.cpp: 定义控制台应用程序的入口点。
//


#include "stdafx.h"
#include<opencv2/opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;
using namespace ml;
ostringstream oss;
int num = -1;
Mat dealimage;
Mat src;
int k = 0;
Mat yangben_gray;
Mat yangben_thresh;

int main()
{

	////===============================读取训练数据===============================////
	const int classsum = 10;//图片共有10类
	const int imagesSum =500;//每类有500张图片			   
	const int imageRows = 20;//图片尺寸
	const int imageCols = 20;
	//训练数据,每一行一个训练图片
	Mat trainingData;
	//训练样本标签
	Mat labels;
	//最终的训练样本标签
	Mat clas;
	//最终的训练数据
	Mat traindata;
	//////////////////////从指定文件夹下提取图片//////////////////
	for (int p = 0; p < classsum; p++)
	{
		oss << "C:/Users/zhang/Desktop/opencv——实例/小案例/车牌检测/基于adaboost机器学习/模版匹配样本/";
		num += 1;//num从0到9
		int label = num;
		oss << num << "/*.jpg";//图片名字后缀,oss可以结合数字与字符串
		string pattern = oss.str();//oss.str()输出oss字符串,并且赋给pattern
		oss.str("");//每次循环后把oss字符串清空
		vector<Mat> input_images;
		vector<String> input_images_name;
		glob(pattern, input_images_name, false);
		//为false时,仅仅遍历指定文件夹内符合模式的文件,当为true时,会同时遍历指定文件夹的子文件夹
		//此时input_images_name存放符合条件的图片地址
		int all_num = input_images_name.size();//文件下总共有几个图片
											   //cout << num << ":总共有" << all_num << "个图片待测试" << endl;

		for (int i = 0; i < imagesSum; i++)
		{
			cvtColor(imread(input_images_name[i]), yangben_gray, COLOR_BGR2GRAY);
			threshold(yangben_gray, yangben_thresh, 0, 255, THRESH_OTSU);
			input_images.push_back(yangben_thresh);
			//循环读取每张图片并且依次放在vector<Mat> input_images内
			dealimage = input_images[i];


			//注意:我们简单粗暴将整个图的所有像素作为了特征,因为我们关注更多的是整个的训练过程
			//,所以选择了最简单的方式完成特征提取工作,除此中外,
			//特征提取的方式有很多,比如LBP,HOG等等
			//我们利用reshape()函数完成特征提取,
			//reshape(1, 1)的结果就是原图像对应的矩阵将被拉伸成一个一行的向量,作为特征向量。
			dealimage = dealimage.reshape(1, 1);//图片序列化
			trainingData.push_back(dealimage);//序列化后的图片依次存入
			labels.push_back(label);//把每个图片对应的标签依次存入
		}
	}

	//图片数据和标签转变下
	Mat(trainingData).copyTo(traindata);//复制
	traindata.convertTo(traindata, CV_32FC1);//更改图片数据的类型,必要,不然会出错
	Mat(labels).copyTo(clas);//复制

	////===============================创建KNN模型===============================////
	Ptr<KNearest>knn = KNearest::create();
	knn->setDefaultK(10);//k个最近领
	knn->setIsClassifier(true);//true为分类,false为回归
	//训练数据和标签的结合
	Ptr<TrainData>trainData = TrainData::create(traindata, ROW_SAMPLE, clas);
	//训练
	knn->train(trainData);

	//model->save("E:/image/KNearestModel.xml"); 

	////===============================预测部分===============================////
	//预测分类
	Mat src = imread("C:/Users/zhang/Desktop/opencv——实例/小案例/车牌检测/基于adaboost机器学习/检测到的车牌字符/4.jpg");
	cvtColor(src, src, COLOR_BGR2GRAY);
	threshold(src, src, 0, 255, CV_THRESH_OTSU);
	imshow("原图像", src);
	Mat input;
	src = src.reshape(1, 1);//输入图片序列化
	input.push_back(src);
	input.convertTo(input, CV_32FC1);//更改图片数据的类型,必要,不然会出错

	float r = knn->predict(input);   //对所有行进行预测
	cout << r << endl;
	waitKey(0);
	return 0;
}




 

 

结果:

 

### 树莓派 OpenCV 实现简单数字识别 #### 准备工作 确保树莓派已安装OpenCV库[^1]。如果尚未安装,可以通过以下命令来完成安装: ```bash sudo apt-get update sudo apt-get install python3-opencv ``` #### 获取资源文件 下载并解压包含数码管数字图像识别方案的资源文件[^2]。此资源文件提供了完整的数码管数字识别代码以及详细的代码注释。 #### 运行环境配置 将代码上传到树莓派,并确认Python环境中能够正常调用OpenCV库。对于初次使用者来说,在执行任何操作之前了解一些基础概念是有益的,比如KNN算法的工作机制及其在计算机视觉领域内的应用方式。 #### 示例代码展示 下面是一段简化版的例子,展示了如何利用OpenCV读取图片、预处理并将之转换为灰度图以便后续处理;接着通过训练好的模型来进行预测。注意这里的`model_path`应该指向你自己的训练集路径。 ```python import cv2 import numpy as np def load_model(model_path): model = cv2.ml.KNearest_create() # 加载预先训练过的knn模型 model.load(model_path) return model def preprocess_image(image_path): img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) resized_img = cv2.resize(img, (28, 28)) flattened_img = resized_img.reshape(1, -1).astype(np.float32) return flattened_img image_path = &#39;path_to_your_digit_image.png&#39; model_path = &#39;path_to_trained_knn_model.xml&#39; # 预加载模型 model = load_model(model_path) # 处理输入图像 processed_image = preprocess_image(image_path) # 执行预测 ret, results, neighbours, dist = model.findNearest(processed_image, k=5) predicted_number = int(results.ravel()[0]) print(f&#39;The predicted number is {predicted_number}&#39;) ``` 这段程序首先定义了一个函数用于加载先前保存下来的KNN分类器实例,另一个则负责接收一张待测的手写体阿拉伯数字照片并将其转化为适合喂入网络的形式——即固定大小(此处设定了28×28像素)、单通道黑白模式下的矩阵形式。最后部分则是实际调用了上述两个辅助工具完成了整个流程:从获取用户指定位置上的原始素材直至输出最终判定结果为止。 #### 测试与验证 按照说明文档中的指导,使用提供的示例图像数据进行初步测试和验证。根据实际情况调整参数或优化性能,直到达到满意的效果为止。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值