opencv_c++学习(二十九)

news2024/9/29 23:35:35

一、监督学习的聚类方法

K近邻的方法:
在这里插入图片描述
首先给出一个阈值k,后寻找距离黑色圆点最近的k个元素,占据比例大的元素即为黑色所属的类别。如图所示,即k=3时,黑色圆属于三角形,k=5时圆点属于正方形。
支持向量机方法:
在这里插入图片描述

virtual bool cv::mliStatModel::train ( const Ptr< TrainData > &trainData, int flags = 0)

trainData:训练时使用的数据,数据为Ptr类型。
flags:构建模型方法标志,例如UPDATE_MODEL表示对使用新数据对模型进行更新。

virtual float cw::mll::StatModal::predict ( llnputArray samiples, results =, OutputArray inolarrayl, int flags =0, const )

samplcs:输入数据矩阵,矩阵数据类型必须是cV_32。results:对输入数据预测结果的输出矩阵。
flags:模型方法标志,取决于具体模型。
创建训练数据的函数:

static Ptr<TrainData>cv::ml::TrainData::create ( InputArray samples, int layout, InputArray responses, InputArray varldx = noArray(), InputArray sampleldx = noArray(), sampleWelights=,
InputArray noArray(),InputArray varType  moArray())

samples:样本数据矩阵,数据类型必须是CV_32F。
layout:样本数据排列方式的标志,ROW_SAMPLE(简记为0)表示每个样本数据为行排列,COL_SAMPLE(简记为1)表示每个样本数据为列排列。
responses:标签矩阵,如果是标量,存储为单行或者单列的矩阵,矩阵数据类型为CV_32F或CV_32S
varldx:用于指定哪些变量用于训练的向量,数据类型为CV_32S。
sampleldx:用于指定哪些样本用于训练的向量,数据类型为CV_32S。sampleWeights:每个样本数据权重向量,数据类型必须是CV_32F。
varType:声明变量类型的标志,VAR_ORDERED表示有序变量,VAR_CATEGORICAL表示分类变量。
创建K近邻方法:

static Ptr<KNearest> cv:umlKNearest:create( )

K近邻方法实现:

virtual float cv::ml::KNearest::findNearest ( InputArray samples, int k outputArray results, neighborResponses =, OutputArray noArray(), OutputArray dist = noArray(), const)

samples:待根据K近邻算法预测的数据,数据需要行排列且数据类型为CV_32F。
k:最近K近邻的数目。
results:每个新数据的预测结果,数据类型为CV_32F。
ncighborResponses:可以选择输出的每个数据最近邻的k个样本。
dist:可以选择输出的与k个最近邻样本的距离。
本节的应用案例如下:

using namespace cv::ml;

int main() {

	//读取图片
	Mat src = imread("1.jpg");
	Mat gray;
	if (src.empty())
	{
		printf("不能打开空图片");
		return -1;
	}

	cvtColor(src, gray, COLOR_BGR2GRAY);

	//将图像分割为5000个cells
	Mat images = Mat::zeros(5000, 400, CV_8UC1);
	Mat labels = Mat::zeros(5000, 1, CV_8UC1);

	int index = 0;
	Rect numberImg;
	numberImg.x = 0;
	numberImg.height = 1;
	numberImg.width = 400;
	for (int row = 0; row < 50; row++)
	{
		//从图像中分割出20*20的图像作为独立数字图像
		int label = row / 5;
		int datay = row * 20;
		for (int col = 0; col < 100; col++)
		{
			int datax = col * 20;
			Mat number = Mat::zeros(Size(20, 20), CV_8UC1);
			for (int x = 0; x < 20; x++)
			{
				for (int y = 0; y < 20; y++)
				{
					number.at<uchar>(x, y) = gray.at<uchar>(x + datay, y + datax);
				}
			}

			//将二维图像转化为行数据
			Mat row = number.reshape(1, 1);
			numberImg.y = index;

			//添加到总数据中
			row.copyTo(images(numberImg));

			//记录每个图像对应的数字标签
			labels.at<uchar>(index, 0) = label;
			index++;				 
		}
	}

	imwrite("结果:", images);
	imwrite("标签:", labels);

	//加载训练数据集
	images.convertTo(images, CV_32FC1); 
	labels.convertTo(labels, CV_32SC1);

	Ptr<ml::TrainData> tdata = ml::TrainData::create(images, ml::ROW_SAMPLE, labels);
	// 创建区近邻类

	Ptr<KNearest> knn = KNearest::create();

	// 每个类别拿出5个数据
	knn->setDefaultK(5); 
	
	// 进行分类
	knn->setIsClassifier(true); 

	//开始训练
	knn->train(tdata);

	//保存训练结果
	knn->save("knn_model.yml");

	waitKey(0);
	return true;
}

其中输入的数据样例为:
在这里插入图片描述
该图片共有5000个数字,每个数字为20*20像素大小,因此需要分割处理。

读取已经保存的模型,并进行预测:

int main() {

	//加载KNN分类器
	Mat data = imread("所有数据按行排列结果.png", IMREAD_ANYDEPTH);
	Mat labels = imread("标签.png", IMREAD_ANYDEPTH);
	data.convertTo(data, CV_32FC1);
	labels.convertTo(labels, CV_32SC1);
	Ptr<KNearest> knn = Algorithm::load<KNearest>("knn_madel.yml");

	//查看分类结果
	Mat result;
	knn->findNearest(data, 5, result);
	// 统计分类结果与真实结果相同的数目
	int count = 0;
	for (int row = 0; row < result.rows; row++)
	{
		int predict = result.at<float>(row, 0); 
		if (labels.at<int>(row, 0) == predict)
		{
			count = count + 1;
		}
	}
	float rate = 1.0*count / result.rows;

	cout << "分类的正确性:" << rate << endl;

	//测试新图像是否能够识别数字
	Mat testImgl = imread("handrite01.png",IMREAD_GRAYSCALE);
	Mat testImg2 = imread("handrite02.png",IMREAD_GRAYSCALE);
	imshow("testIng1", testImgl) ;
	imshow("testImng2",testImg2);

	//缩放到20×20的尺寸
	resize(testImgl, testImgl, Size(20, 20));
	resize(testImg2, testImg2, Size(20, 20));
	Mat testdata = Mat::zeros(2, 400, CV_8UC1);

	//将数据改写成行的形式
	Rect rect;
	rect.x = 0;
	rect.y = 0;
	rect.height = 1; 
	rect.width = 400;
	Mat oneDate = testImgl.reshape(1, 1);
	Mat twoData = testImg2.reshape(1, 1);
	oneDate.copyTo(testdata(rect));

	rect.y = 1;
	twoData.copyTo(testdata(rect));
	
	//数据类型转换
	testdata.convertTo(testdata, CV_32F);

	//进行估计识别
	Mat result2;
	knn->findNearest(testdata, 5, result2);

	//查看预测结果
	for (int i = 0; i < result2.rows; i++)
	{
		int predict = result2.at<float>(i, 0);
		cout << "第" << i + 1 << "图像预测结果:" << predict << "真实结果:" << i + 1 << endl;
	}

	waitKey(0);
	return 0;
}

二、K均值聚类

K均值聚类的步骤:
Step1:指定将数据聚类成k类,并随机生成k个中心点。
Step2:遍历所有数据,根据数据与中心的位置关系将每个数据归类到不同的中心里。
Step3:计算每个聚类的平均值,并将均值作为新的中心点。
Step4:重复Step2和Step3,直到每个聚类中心点的坐标收敛,输出聚类结果。

double cv::kmeans ( InputArray data, int K, InputOutputArray bestLabels,TermCriteria criteria, int attempts, int flags, OutputArray centers = noArray())

data:需要聚类的输入数据,数据必须行排列,即每一行是一个单独的数据。
K:将数据聚类的种类数目。
bestLabels:存储每个数据聚类结果索引的矩阵或向量。
criteria:迭代算法终止条件。
attempts:表示采样不同初始化标签尝试的次数。
flags:每类中心坐标初始化方法标志。
centers:最终聚类后的每个类的中心位置坐标。
使用聚类对图像进行分割的样例如下:

int main() {

	//读取图片
	Mat src = imread("1.png");
	if (src.empty())
	{
		printf("不能打开空图片");
		return -1;
	}

	//定义五种图像的颜色
	Vec3b colorLut2[5] = {
		Vec3b(0,0,255),
		Vec3b(0,255,0),
		Vec3b(255,0,0),
		Vec3b(0,255,255),
		Vec3b(255,0,255)
	};

	//图像的尺寸,用于计算图像中像素点的数目
	int width = src.cols ;
	int height = src.rows;

	//初始化定义
	int sampleCount = width * height;

	//将图像矩阵数据转换成每行一个数据的形式
	Mat sample_data = src.reshape(3, sampleCount); 
	Mat data;
	sample_data.convertTo(data, CV_32F);

	// KMean函数将像素值进行分类
	// 分割后的颜色种类
	int number2 = 3;	
	Mat labels2;

	TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 0.1);
	kmeans(data, number2, labels2, criteria, number2, KMEANS_PP_CENTERS);

	//显示图像分割结果
	Mat result = Mat::zeros(src.size(), src.type()); 
	for (int row = 0; row < height; row++)
	{
		for (int col = 0; col < width; col++)
		{
			int index = row * width + col;
			int label = labels2.at<int>(index, 0);
			result.at<Vec3b>(row, col) = colorLut2[label];
		}
	}
	namedWindow("原图", WINDOW_NORMAL);
	imshow("原图", src);

	namedWindow("分割", WINDOW_NORMAL);
	imshow("分割", result);

	waitKey(0);
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/585945.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式-享元模式

问题背景 有一个小型的外包项目&#xff0c;就是给客户A做一个展示的网站&#xff0c;例如展示&#xff1a;这个网站展示的都是客户A的产品。然后可以A的朋友觉得不错&#xff0c;也希望做这样一个网站&#xff0c;但是要求有些不同&#xff0c;要求以新闻的形式展示。还有更多…

DORIS----漏斗转化分析案例实现

综合案例之漏斗转化分析 业务目标、到达路径&#xff0c;路径步骤、步骤人数&#xff0c;步骤之间的相对转换率和绝对转换率 每一种业务都有他的核心任务和流程&#xff0c;而流程的每一个步骤&#xff0c;都可能有用户流失。 所以如果把每一个步骤及其对应的数据&#xff08;…

【Linux】深入了解冯诺依曼体系结构与操作系统

目录 导读 &#x1f31e;专栏导读 &#x1f31e;冯诺依曼 &#x1f31e;冯诺依曼体系结构 &#x1f31b;木桶效应 &#x1f31e;操作系统(Operator System) &#x1f31b;概念 &#x1f31b;设计OS的目的 &#x1f31b;系统调用和库函数概念 导读 六一儿童节快到了&…

Envoy 物联网模块开发---串口服务器 (一)

一、背景 最近业余时间想基于Envoy 开发一个串口网关&#xff0c;主要是想把一些 modbus、bacnet 以及 mqtt 等物联网协议接入Envoy中&#xff0c;当读到串口数据后可以转发成对应的网络协议 二、Envoy的优势 选择Envoy的话主要是因为Envoy的代码已经十分健全了&#xff0c;零…

(数字图像处理MATLAB+Python)第九章图像形态学运算-第三节:二值图像的形态学处理

文章目录 一&#xff1a;形态滤波&#xff08;1&#xff09;概述&#xff08;2&#xff09;程序 二&#xff1a;图像的平滑处理&#xff08;1&#xff09;概述&#xff08;2&#xff09;程序 三&#xff1a;图像的边缘提取&#xff08;1&#xff09;概述&#xff08;2&#xff…

redux与react-redux状态集中管理

一、redux:可用于react、Vue等中 redux应用&#xff1a;状态的管理&#xff0c;共享状态&#xff0c;Redux用一个单独的常量状态树&#xff08;state对象&#xff09;保存这一整个应用&#xff08;如tab选项卡的状态、城市等需要应用在整个页面的信息&#xff09;的状态。其本…

算法|13.贪心

1.字典序最小的字符串连接方案 题意&#xff1a;给定一个由字符串组成的数组strs&#xff0c;必须把所有的字符串拼接起来&#xff0c;返回所有可能的拼接结果中字典序最小的结果。 public static class MyCom implements Comparator<String>{Overridepublic int compa…

@程序员【提升代码质量,快走出学习迷茫的状态吧】

思路清晰&#xff0c;能上钻一 思路清晰&#xff0c;能上钻一写代码如同打游戏上分。写代码如同中医治病。 思路清晰&#xff0c;能上钻一 ⭐⭐想成为一名优秀的电玩高手&#xff0c;你需要有清晰的思路;想成为一名顶级的电玩高手&#xff0c;你需要的是顶级的思路和异于常人的…

裁员后投递了300次简历,面试22家,终于上岸!

这是一位群友的励志故事&#xff0c;生活虽然很苦&#xff0c;但是朝着自己想要的方向去努力很值得&#xff01; 求职109天&#xff0c;沟通2212次&#xff0c;投简历355次&#xff0c;面试22家&#xff0c;涨薪10%&#xff0c;终于上岸&#xff0c;在这里复盘下我的经历&#…

[创业之路-72] :创业公司发展模式的选择:技工贸还是贸工技?

目录 前言&#xff1a; 一、什么是技、工、贸&#xff1f; 二、概述 2.1 推动力不同 2.2 适合领域不同 2.3 经营模式的主导地位不同 三、技、工、贸详解 3.1 常见的七种营销模式 3.2 常见的三种生产模式 3.3 常见的三种研发模式 四、经营模式的战略选择与影响因素 …

短视频矩阵源码如何做应用编程?

短视频矩阵源码&#xff0c; 短视频矩阵系统技术文档&#xff1a; 可以采用电子文档或者纸质文档的形式交付&#xff0c;具体取决于需求方的要求。电子文档可以通过电子邮件、远程指导交付云存储等方式进行传输、 短视频矩阵{seo}源码是指将抖音平台上的视频资源进行筛选、排…

C++ Primer Plus 第一,二章笔记

目录 第一章笔记 1、C简介 2、C简史 3、可移植性和标准 第二章笔记 1. 进入C 1.3、预处理器和头文件 1.4、名称空间&#xff08;namespace&#xff09; 1.5、使用cout进行C的输出 2. C语句 3. 其他C语句 4. 函数 第一章笔记 1、C简介 C融合了3种不同的编程方式&a…

vsdx文件怎么打开,安装什么软件打开这种后缀名(教程)

目录 简介 安装配置 其他 总结 简介 VSDX 文件是 Microsoft Visio 文件格式&#xff0c;它是一种二进制文件&#xff0c;用于保存 Visio 中的绘图和图表。如果你想要打开 VSDX 文件&#xff0c;可以考虑以下几种方法&#xff1a; 方法一&#xff1a;使用 Microsoft Visio …

C++IO流(详解)

C语言的输入与输出 在C语言当中&#xff0c;我们使用最频繁的输入输出方式就是scanf与printf&#xff1a; scanf&#xff1a; 从标准输入设备&#xff08;键盘&#xff09;读取数据&#xff0c;并将读取到的值存放到某一指定变量当中。 printf&#xff1a; 将指定的数据输出到…

Vivado综合属性系列之十三 FSM_ENCODING

目录 一、前言 二、FSM_ENCODING ​2.1 属性介绍 ​2.2 工程代码 2.3 结果 ​2.4 参考资料 一、前言 ​状态机的实现有很多方式&#xff0c;如auto&#xff0c;one_hot&#xff0c;sequential&#xff0c;如下图中Synthesis中-fsm_extraction的配置项&#xff0c;但此处作用范…

【AI面试】降低过拟合的方式方法横评探究

对于一个“训练调参工程师”来说&#xff0c;在训练过程遇到过拟合现象&#xff0c;是常事。当然&#xff0c;如何降低过拟合&#xff0c;也是在面试过程中&#xff0c;经常被面试官问到的问题&#xff08;没啥可问的&#xff0c;就只能这样问了&#xff09;。以下是我们会常考…

HEVC中,mvd怎么写进码流的?

文章目录 Motion vector difference syntax 标准文档描述语义解释设计意义 Motion vector difference syntax 标准文档描述 语义解释 MvdL1[ x0 ][ y0 ][ compIdx ] L1列表的mvd x0,y0 表示亮度快左上角坐标 compIdx 0表示水平 compIdx 0表示垂直 mvd_l1_zero_flag&#xff1a…

DRF之JWT认证

一、JWT认证 在用户注册或登录后&#xff0c;我们想记录用户的登录状态&#xff0c;或者为用户创建身份认证的凭证。我们不再使用Session认证机制&#xff0c;而使用Json Web Token&#xff08;本质就是token&#xff09;认证机制。 Json web token (JWT), 是为了在网络应用环…

给osg::Geometry(自己绘制的几何体)添加纹理(二)

目录 1. 前言 2. 自会集合体贴纹理 2.1. 一张图贴到整个几何体 2.2. 几何体每个面贴不同的图片纹理 3. 说明 1. 前言 前文讲述了如何给osg自带的几何体&#xff0c;如&#xff1a;BOX等&#xff0c;添加纹理&#xff0c;文章参考链接如下&#xff1a; osg给osg::Geometry&…

动态规划专题一(动态规划的基本模型)

先上例题1 1258&#xff1a;【例9.2】数字金字塔 信息学奥赛一本通&#xff08;C版&#xff09;在线评测系统 (ssoier.cn) 1258&#xff1a;【例9.2】数字金字塔 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 36341 通过数: 21547 【题目描述】 观察下面的数字…