在用字符识别上进行测试
训练集3000张图片
测试集2000张图片
这3000和2000的图像没有重复的

Knn:
目标:将待测物分类成多个类别
输入:待测物(已知类别集合D,其中包含j个已知类别)
输出:项目可能的类别。

优点:
算法简单,易于实现,不需要参数统计,不需要事先训练

缺点:
KNN计算量特别大,而且训练样本必须存储在本地,内存开销也特别大
K的取值(一般不大于20)
opencv提供了一张图片,在路径C:/opencv/sources/samples/data/digits.png下
如下图所示:

仔细看,其中都是手写的数字,是0~9之间,数字每个大小一致,宽高为20*20,
每个进行序列化,然后可以得到一共5000个样品,选择其中的3000个进行训练。
如果横着进行训练,那么最下面的9就训练不到了,所以竖着进行训练,那样0~9就都训练到了

代码如下:

#include<opencv2/opencv.hpp>
#include<iostream>using namespace std;
using namespace cv;
using namespace cv::ml;int main(int argc, char** argv)
{//读取图片Mat cvImg = imread("C:/opencv/sources/samples/data/digits.png");//真正测试的灰度图片Mat cvGrayImg;//从原图转换成灰度图cvtColor(cvImg, cvGrayImg, CV_BGR2GRAY);//图像的宽高如下2000*1000int nWidth = cvGrayImg.cols;int nHeiht = cvGrayImg.rows;//经过查看,分成20*20的小图片,将宽/20,高也/20int nCrop = 20;int nSmallWidth = nWidth / nCrop;int nSmallHeight = nHeiht / nCrop;Mat vImgData;     //所有图像数据扁平化存储Mat    vImgLabels;   //所有图像的标注数据//共计100*50=5000个数据for (int i = 0; i < nSmallWidth; i++){//每一列的纵坐标需要偏移如下int offsetCol = i*nCrop;for (int j = 0; j < nSmallHeight; j++){//每一行的横坐标需要偏移如下int offsetRow = j*nCrop;//在cvGrayImg上截取20*20的小图像,拷贝到tempImg上Mat tempImg;cvGrayImg(Range(offsetRow, offsetRow + nCrop), Range(offsetCol, offsetCol + nCrop)).copyTo(tempImg);//tempImg图像本身是一个20*20的矩阵,进行变换,通道数不变,将矩阵序列化成1行N列的行向量。//可以理解成这个vImgData数组中有所有小图像的数据,但是是以行向量的形式存储的.相当于图像数据在这里只有一行,但是有20*20=400列vImgData.push_back(tempImg.reshape(0, 1));//这次是因为里面的数据就是0,1,2,3,如果是字母的话,可能需要在这里人工的输入这些字母。//数据的扫描。因为外面的循环是nSmallHeight,所以每次先扫描每一列,数据是0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3....vImgLabels.push_back((int)j / 5);}}//数据大小没有变化,但是类型由uchar变为了cv_32f位vImgData.convertTo(vImgData, CV_32F);//所有图像数量,即上述的5000int nImgCount = vImgData.rows;//选择其中的3000张作为训练样本int nTrainCount = 3000;Mat trainData, trainLabels;//前4000个样本为训练数据//理解为截取vImgData这个容器里面顺序0到nTrainCount的数据trainData = vImgData(Range(0, nTrainCount), Range::all());   trainLabels = vImgLabels(Range(0, nTrainCount), Range::all());//使用KNN算法int K = 5;//设置训练数据,固定用法//训练数据为trainData,且已经标注好trainLabels。待测数据为tData.Ptr<TrainData> tData = TrainData::create(trainData, ROW_SAMPLE, trainLabels);创建knn分类器Ptr<KNearest> model = KNearest::create();// 设定k值model->setDefaultK(K);model->setIsClassifier(true);// 设置训练数据,进行训练。就相当于将前面的标注数据和测试数据进行了一个训练绑定model->train(tData);//就上述的几行,就代码Knn训练完毕了//预测分类//训练Ok的图像数量int nTrainOkCount = 0;//测试OK的图片数量int nTestOkCount = 0;//所有样本进行测试for (int i = 0; i < nImgCount; i++){//选择待测图像Mat imgForTest = vImgData.row(i);//用KNN分类器对待测参数进行测试//参数是测试样品,每行作为一个测试数据,即要将每一个样品处理成导入的模型同样维度大小的一行数据,//返回值代表测试出的结果int nResult =(int) model->predict(imgForTest);//第i个数据,在vImgLabels中的值是多少,即这个数据实际结果是什么int nTempLabel = vImgLabels.at<int>(i);//测试结果和标注结果的差值,==0说明是正确的,!=0说明是错误的int nOffset = nResult - nTempLabel;bool bTempResult = false;if (nOffset==0){bTempResult = true;}if (i < nTrainCount){//前3000张图跑都是训练集里面的图像       if (bTempResult){//说明该次训练是ok的,训练正确的总数+1nTrainOkCount++;}}else{//剩余的是测试集里面的图像if (bTempResult){//说明该次测试是ok的,测试正确的总数+1nTestOkCount++;}}}double dTrainOkPercent =(double) nTrainOkCount / nTrainCount;double dTesrOkPercent = (double)nTestOkCount / (nImgCount-nTrainCount);printf("统计: 训练合格率 = %.2f%%, 测试合格率 = %.2f%%\n", dTrainOkPercent*100., dTesrOkPercent*100.);waitKey(0);return 0;
}

测试出的结果如下:

对于这个合格率和KNN系数,做了一个对应的表格

所以K参数选择5

关于KNN的原理,可以查看下面的链接
https://blog.csdn.net/qq_36330643/article/details/77532161
关于距离的理解,可以看下面的链接
https://blog.csdn.net/saltriver/article/details/52502253

OpenCV:Knn算法相关推荐

  1. 分类算法matlab实例,数据挖掘之分类算法---knn算法(有matlab例子)

    knn算法(k-Nearest Neighbor algorithm).是一种经典的分类算法.注意,不是聚类算法.所以这种分类算法 必然包括了训练过程. 然而和一般性的分类算法不同,knn算法是一种懒 ...

  2. 教你用OpenCV实现机器学习最简单的k-NN算法

    前言:OpenCV 的构建是为了提供计算机视觉的通用基础接口,现在已经成为经典和最优秀的计算机视觉和机器学习的综合算法工具集.作为一个开源项目,研究者.商业用户和政府部门都可以轻松利用和修改现成的代码 ...

  3. 手把手教你用OpenCV实现机器学习最简单的k-NN算法(附代码)

    导读:OpenCV 的构建是为了提供计算机视觉的通用基础接口,现在已经成为经典和最优秀的计算机视觉和机器学习的综合算法工具集.作为一个开源项目,研究者.商业用户和政府部门都可以轻松利用和修改现成的代码 ...

  4. Python+OpenCV:理解k近邻(kNN)算法(k-Nearest Neighbour (kNN) algorithm)

    Python+OpenCV:理解k近邻(kNN)算法(k-Nearest Neighbour (kNN) algorithm) 理论 kNN is one of the simplest classi ...

  5. 【OpenCV/C++】KNN算法识别数字的实现原理与代码详解

    KNN算法识别数字 一.KNN原理 1.1 KNN原理介绍 1.2 KNN的关键参数 二.KNN算法识别手写数字 2.1 训练过程代码详解 2.2 预测分类的实现过程 三.KNN算法识别印刷数字 2. ...

  6. OpenCV——KNN分类算法 摘

    KNN近邻分类法(k-Nearest Neighbor)是一个理论上比较成熟的方法,也是最简单的机器学习算法之一. 这个算法首先贮藏所有的训练样本,然后通过分析(包括选举,计算加权和等方式)一个新样本 ...

  7. KNN算法与Kd树(转载+代码详细解释)

    最近邻法和k-近邻法 下面图片中只有三种豆,有三个豆是未知的种类,如何判定他们的种类? 提供一种思路,即:未知的豆离哪种豆最近就认为未知豆和该豆是同一种类.由此,我们引出最近邻算法的定义:为了判定未知 ...

  8. 什么是k-NN算法?怎样实现?终于有人讲明白了

    导读:使用分类模型预测类标签. 作者:阿迪蒂亚·夏尔马(Aditya Sharma).维什韦什·拉维·什里马利(Vishwesh Ravi Shrimali).迈克尔·贝耶勒(Michael Beye ...

  9. python 数学公式识别_Python实现基于KNN算法的笔迹识别功能详解

    本文实例讲述了Python实现基于KNN算法的笔迹识别功能.分享给大家供大家参考,具体如下: 需要用到: Numpy库 Pandas库 手写识别数据 点击此处本站下载. 数据说明: 数据共有785列, ...

  10. OpenCV-Python实战(番外篇)——利用 KNN 算法识别手写数字

    OpenCV-Python实战(番外篇)--利用 KNN 算法识别手写数字 前言 手写数字数据集 MNIST 介绍 基准模型--利用 KNN 算法识别手写数字 改进模型1--参数 K 对识别手写数字精 ...

最新文章

  1. android垂直排列元素_Android弹性布局(FlexboxLayout)
  2. Spark读取文本文件并转换为DataFrame
  3. spring(10)通过spring 和 JDBC征服数据库
  4. c语言生日创意代码_用C语言写个代码,利用空格和符号拼写出生日快乐之类的...
  5. 在docker容器中安装ifconfig、ping等工具
  6. [国家集训队]聪聪可可
  7. python在机械行业的应用_Python语言程序设计与应用-教学大纲
  8. java实现远程控制应用
  9. 数据标注:语义分割数据标注工具labelme安装、使用方法
  10. 第十四周助教工作总结——NWNU李泓毅
  11. 中国农业会计杂志中国农业会计杂志社中国农业会计编辑部2022年第12期目录
  12. 分析与思考 黄奇帆的复旦经济课 读书笔记
  13. 美创科技入选第九届CNCERT网络安全应急服务支撑单位
  14. tensorflow框架下,多进程model.predict(x)无响应/暂停/无输出
  15. Spark 学习入门教程
  16. 【MATLAB实验】MATLAB图形绘制相关函数与定积分计算
  17. 第10章 路由器、交换机及其操作系统介绍
  18. MATLAB中SSQJ,基于lqr的一级倒立摆仿真研究
  19. 微软 Outlook 升级,集成轻量级 CRM 功能
  20. 前端和后端的区别是什么?

热门文章

  1. IEEE1588 Precision Time Protocol(PTP)
  2. 如何查看自己网站的访问量
  3. 安装ADOBE READER时无法将数值写入键_php_sir_新浪博客
  4. Annovar软件注释肿瘤基因突变(一):COSMIC数据库最新版下载与使用
  5. ctDNA早期肿瘤×××基因检测
  6. 学员管理系统(完整版)
  7. JustinMind
  8. android5去wifi感叹号,android 5.1 WIFI图标上的感叹号及其解决办法
  9. 负折射率波导matlab,介质波导的数值模拟
  10. HTML abbr 标签