《opencv实用探索·二十二》支持向量机SVM用法

1、概述
在了解支持向量机SVM用法之前先了解一些概念:
(1)线性可分和线性不可分
如果在一个二维空间有一堆样本,如下图所示,如果能找到一条线把这两类样本分开至线的两侧,那么这个样本集就是线性可分,否则就是线性不可分。
在这里插入图片描述
如果在一个三维空间有一堆样本,如果能找到一个平面把三维空间中的两类样本分开至平面的两侧,那么这个样本就是线性可分,否则为线性不可分。
如果在一个超过三维空间的更高维度上能找一个平面(这里我们称这个平面为超平面)把两类样本分开至超平面两侧,那么这个样本就是线性可分,否则为线性不可分。

一般情况下,把能够可以被一条直线(更一般的情况,即一个超平面)分割的数据称为线性可分的数据,所以超平面是线性分类器。

(2)支持向量机(Support Vector Machine,SVM)
在OpenCV中,支持向量机(Support Vector Machine,SVM)是一种用于图像分类和对象识别的机器学习算法。SVM 是一种监督学习算法,它可以用于二分类或多分类问题。在图像处理领域,SVM 经常用于训练分类器,从而对图像中的对象进行识别。

SVM 的基本思想是找到一个最优的超平面,将不同类别的样本分开,并且使得两个类别之间的间隔最大化。这个最优的超平面由支持向量(Support Vectors)定义,它们是离超平面最近的样本点。该怎么理解这句话?

我们还是以一个二维平面的样本集为例,如下图所示:
L1,L2,L3都可以把两类样本分离,L1离P1样本向量最近,L3离P2样本向量最近,我们称这两个样本向量为支持向量,这两条线(更宽泛一点称为超平面)称为支撑超平面,他们分别支撑两类数据。L1和L3之间的距离d称为间隔,我们需要找到一个最好的超平面L2使得间隔最大。
在这里插入图片描述

2、支持向量机SVM用法步骤
在OpenCV中,SVM的使用通常涉及以下步骤:
(1)数据准备: 收集并准备训练数据,确保每个样本都有相应的标签。
(2)创建SVM对象: 使用OpenCV的 cv::ml::SVM 类创建一个SVM对象。
(3)设置训练参数: 设置SVM的训练参数,例如核函数、惩罚系数等。
(4)训练SVM模型: 使用训练数据对SVM进行训练。
(5)预测: 使用训练好的SVM模型对新的数据进行分类预测。

1.数据准备
训练数据(Training Data): 这是用于训练SVM模型的输入数据集。对于分类问题,每个训练样本都是一个输入向量,表示数据的特征。下面代码中,trainingDataMat 是一个矩阵,每一行代表一个样本,每一列代表一个特征。在这个例子中,每个样本有两个特征,分别是 x 和 y 的坐标。

// 设置训练数据
float trainingData[4][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501} };
Mat trainingDataMat(4, 2, CV_32FC1, trainingData);

如果把这4个点在图像上标出来,大致位置如下图所示(注意:501表示像素的列,10表示像素的行,其他坐标也是如此),同时根据下面设置的样本标签来看,图中右上角的点为正样本,其余为负样本,图中红线位置大概就是超平面,把两类样本分至两侧。
在这里插入图片描述
标签(Labels): 这是训练数据对应的输出标签或类别。标签表示每个训练样本所属的类别。在下面代码中,labelsMat 是一个矩阵,每一行对应于训练数据中的一个样本,表示该样本所属的类别。通常,标签是整数值,例如 1 表示正类别,-1 表示负类别。

// 设置标签
int labels[4] = { 1, -1, -1, -1 };
Mat labelsMat(4, 1, CV_32SC1, labels);

对于上面的四个训练样本,每个样本有两个特征。对应的标签是 {1, -1, -1, -1}。这表示第一个样本属于正类别(1),而其余三个样本属于负类别(-1)。这些训练数据和标签将用于训练支持向量机模型,使其能够对新的输入数据进行分类。

2.创建SVM对象

//如果使用OpenCV 4.x 版本请用如下代码
Ptr<SVM> svm = SVM::create();//如果使用OpenCV 3.x版本请用如下代码
SVM::Params params;

3.设置SVM的训练参数

//如果使用OpenCV 4.x 版本请用如下代码
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));//如果使用OpenCV 3.x版本请用如下代码
params.svmType = SVM::C_SVC;
params.kernelType = SVM::LINEAR;
params.termCrit = TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6);

setType 用于设置 SVM 的类型,即分类器的类型。
SVM 的类型:
cv::ml::SVM::C_SVC:用于分类。
cv::ml::SVM::NU_SVC:用于分类,支持类别不平衡。
cv::ml::SVM::ONE_CLASS:用于单类别分类。
cv::ml::SVM::EPS_SVR:用于回归问题。
cv::ml::SVM::NU_SVR:用于回归问题,支持回归损失参数。

setKernel 用于设置核函数,即 SVM 在高维空间中处理数据的方法
核函数:
cv::ml::SVM::LINEAR:线性核函数,它适用于线性可分的数据。
cv::ml::SVM::POLY:多项式核函数。
cv::ml::SVM::RBF:径向基核函数(高斯核函数)。
cv::ml::SVM::SIGMOID:Sigmoid 核函数。

setTermCriteria 用于设置 SVM 的终止标准,即训练停止的条件。
cv::TermCriteria::MAX_ITER 表示基于最大迭代次数的终止标准,这里设置为最大迭代次数为 100。
1e-6 是一个容差,表示允许的训练误差

4.训练SVM模型

//如果使用OpenCV 4.x 版本请用如下代码
svm->train(trainingDataMat, ROW_SAMPLE, labelsMat);//如果使用OpenCV 3.x版本请用如下代码
Ptr<SVM> svm = StatModel::train<SVM>(trainingDataMat, ROW_SAMPLE, labelsMat, params);

ROW_SAMPLE: 这是一个标志,表示每行数据是一个训练样本。在分类问题中,每行通常代表一个样本,每列是该样本的特征。这个标志告诉函数按行处理数据

svm->train() 函数用于训练 SVM 模型。在训练期间,模型将学会如何将输入数据映射到给定的类别,以便在未知数据上进行分类。

5.预测
使用训练好的SVM模型对数据进行预测
假如有一个图像宽高都是512,现在把图像中每个像素的坐标作为一个新输入的样本,并对这个样本进行预测是正样本还是负样本,如果是正样本就用绿色标出,如果是负样本就用蓝色标出。

Vec3b green(0, 255, 0), blue(255, 0, 0);//显示由SVM给出的决定区域 (Show the decision regions given by the SVM)for (int i = 0; i < image.rows; ++i)for (int j = 0; j < image.cols; ++j){//把图像中每个像素点的坐标作为一个样本进行创建,i是行对应y坐标,j是列对应x坐标Mat sampleMat = (Mat_<float>(1, 2) << j, i);//使用训练好的 SVM 模型对当前像素的特征进行分类。response 存储了 SVM 模型对该样本的预测结果//response 为1表示正样本用绿色标出,为-1表示负样本用蓝色标出float response = svm->predict(sampleMat);if (response == 1)image.at<Vec3b>(i, j) = green;else if (response == -1)image.at<Vec3b>(i, j) = blue;}

这样,通过遍历整个图像,根据 SVM 模型的分类结果,将图像的不同区域标记为不同的颜色,从而可视化 SVM 模型对数据的分类效果
在这里插入图片描述

最后在画出训练数据和支持向量

//显示训练数据 (Show the training data)int thickness = -1;int lineType = 8;circle(image, Point(501, 10), 5, Scalar(0, 0, 0), thickness, lineType);circle(image, Point(255, 10), 5, Scalar(255, 255, 255), thickness, lineType);circle(image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType);circle(image, Point(10, 501), 5, Scalar(255, 255, 255), thickness, lineType);//显示支持向量 (Show support vectors)thickness = 2;lineType = 8;Mat sv = svm->getSupportVectors();  //返回的是支持向量的坐标std::cout << "Support Vectors:\n" << sv << std::endl;  //[-0.008130081, 0.008163265]for (int i = 0; i < sv.rows; ++i)  //rows为1,表示每个样本类别中只有一个支持向量{const float* v = sv.ptr<float>(i);int x = (int)v[0];int y = (int)v[1];circle(image, Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), thickness, lineType);}

在这里插入图片描述
我的理解是支持向量应该是上面样本中的某个样本的坐标,这里为啥是[-0.008130081, 0.008163265]?
支持向量坐标是相对于输入特征空间的,不是图像坐标,“特征空间” 是指用于训练 SVM 模型的样本数据的特征表示的空间,这些坐标在特征空间中描述了支持向量的位置。由于 SVM 的实现可能对数据进行了缩放或标准化,因此这些坐标可能是相对于某种处理后的特征空间而言的。

最后附上完整的代码:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
using namespace cv;
using namespace cv::ml;int main()
{// 视觉表达数据的设置(Data for visual representation)int width = 512, height = 512;Mat image = Mat::zeros(height, width, CV_8UC3);//建立训练数据( Set up training data)int labels[4] = { 1, -1, -1, -1 };Mat labelsMat(4, 1, CV_32SC1, labels);float trainingData[4][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501} };Mat trainingDataMat(4, 2, CV_32FC1, trainingData);std::cout << trainingDataMat << std::endl;//设置支持向量机SVM的参数(Set up SVM's parameters)Ptr<SVM> svm = SVM::create();svm->setType(SVM::C_SVC);svm->setKernel(SVM::LINEAR);svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));// 训练支持向量机(Train the SVM)svm->train(trainingDataMat, ROW_SAMPLE, labelsMat);Vec3b green(0, 255, 0), blue(255, 0, 0);//显示由SVM给出的决定区域 (Show the decision regions given by the SVM)for (int i = 0; i < image.rows; ++i)for (int j = 0; j < image.cols; ++j){Mat sampleMat = (Mat_<float>(1, 2) << j, i);float response = svm->predict(sampleMat);if (response == 1)image.at<Vec3b>(i, j) = green;else if (response == -1)image.at<Vec3b>(i, j) = blue;}//显示训练数据 (Show the training data)int thickness = -1;int lineType = 8;circle(image, Point(501, 10), 5, Scalar(0, 0, 0), thickness, lineType);circle(image, Point(255, 10), 5, Scalar(255, 255, 255), thickness, lineType);circle(image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType);circle(image, Point(10, 501), 5, Scalar(255, 255, 255), thickness, lineType);//显示支持向量 (Show support vectors)thickness = 2;lineType = 8;Mat sv = svm->getSupportVectors();std::cout << "Support Vectors:\n" << sv << std::endl;for (int i = 0; i < sv.rows; ++i){const float* v = sv.ptr<float>(i);int x = (int)v[0];int y = (int)v[1];circle(image, Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), thickness, lineType);}imwrite("result.png", image);        // 保存图像imshow("SVM Simple Example", image); // 显示图像waitKey(0);}
在这里插入图片描述

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

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

相关文章

GIS之深度学习03:Anaconda无法正常启动问题汇总(更新)

在安装完成anaconda后&#xff0c;总会出现一些问题&#xff0c;以下为遇到的问题及解决方案&#xff1a; &#xff08;有问题请私信&#xff0c;持续更新&#xff09; 01&#xff1a;anaconda navigator启动时一直卡在 loading applications 页面 解决&#xff1a; 找到anac…

水库安全监测方案(福建地区水库安全监测案例分享)

我司星创易联最近在福建省受到了一个水库安全监测系统项目的委托。该水库位于福建中部山区,作为该地区的重要防洪与供水工程,对下游数十万人的生活产生重大影响。但是因为水库附近地质情况复杂,水库大坝在多次洪水冲击下出现一定病害,亟须全面加强对水库大坝安全状况的监测,以确…

使用Docker部署Nacos集群和Nginx高可用负载(9节点集群部署)

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容部署Nacos集群Nginx高可用负载 &#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍 &#x1f31f;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专…

力扣5. 最长回文子串(双指针、动态规划)

Problem: 5. 最长回文子串 文章目录 题目描述思路复杂度Code 题目描述 思路 思路1&#xff1a;双指针 1.我们利用双指针从中间向两边扩散来判断是否为回文串&#xff0c;则关键是找到以s[i]为中心的回文串&#xff1b; 2.我们编写一个函数string palindrome(string &s, in…

复盘昨天的内容

vue调节css 后端做业务处理 1.分类管理 GetMapping("/queryCtc")public ApiResult queryCtc(){return ctcService.queryCtc();}/*** 修改类目信息* return*/PutMapping("/updateCtc")public ApiResult updateCtc(RequestBody ShopCtc shopCtc){return c…

【论文阅读】基于人工智能目标检测与跟踪技术的过冷流沸腾气泡特征提取

Bubble feature extraction in subcooled flow boiling using AI-based object detection and tracking techniques 基于人工智能目标检测与跟踪技术的过冷流沸腾气泡特征提取 期刊信息&#xff1a;International Journal of Heat and Mass Transfer 2024 级别&#xff1a;EI检…

硬件监控:使用ipmitool实现Linux系统下对服务器硬件监控

一、监控背景 运维人员对服务器硬件监控主要通过主机人员日常巡检&#xff0c;以及zabbix监控。zabbix监控仅限于服务器CPU、内存故障等导致宕机或者重启从而触发主机状态告警&#xff0c;单个磁盘挂载文件系统因坏盘导致文件系统读写异常&#xff0c;其他情况下zabbix很难监控…

Vue3.0+vue-router 实现权限路由方案一

定义路由 const routes[{path: /page,name: "dashboard",redirect: /page/home,meta: {title: "首页",},component: () > import(/components/layout/index.vue),children: [{path: home,name: "home",meta: {title: "仪表盘",ro…

MongoDB之MongoDBConnectorBI安装与使用

MongoDB之MongoDBConnectorBI安装与使用 文章目录 MongoDB之MongoDBConnectorBI安装与使用1. What is the MongoDB Connector for BI?1. 官网2. 是什么&#xff1f;3. 主要功能和作用4. 应用用场景 2. 安装及说明1. 前提条件2. 在Windows下的安装3.启动与运行1. 配置2. 启动mo…

计算机网络:路由协议

路由协议简介 路由协议是计算机网络中不可或缺的一部分&#xff0c;它们负责确定数据包从源地址到目的地址的最佳路径。想象一下&#xff0c;如果你是一个数据包&#xff0c;路由协议就像是地图或导航工具&#xff0c;指导你如何到达目的地。 目录 路由协议简介 工作原理简化…

开源大模型LLM大爆发,数据竞赛已开启!如何使用FuseLLM实现大语言模型的知识融合?

开源大模型LLM大爆发&#xff0c;数据竞赛已开启&#xff01;如何使用FuseLLM实现大语言模型的知识融合&#xff1f; 现在大多数人都知道LLM是什么&#xff0c;以及可以做什么。 人们讨论着它的优缺点&#xff0c;畅想着它的未来&#xff0c; 向往着真正的AGI&#xff0c;又有…

prometheus告警

alter 告警 下载解压安装 wget https://github.com/prometheus/alertmanager/releases/download/v0.26.0/alertmanager-0.26.0.linux-amd64.tar.gz tar -zxvf alertmanager-0.26.0.linux-amd64.tar.gz -C /usr/local mv alertmanager-0.26.0.linux-amd64 alertmanager配置起启…

Vue插件之Plugins

插件 (Plugins) 是一种能为 Vue 添加全局功能的工具代码。 通过 app.component() 和 app.directive() 注册一到多个全局组件或自定义指令。 通过 app.provide() 使一个资源可被注入进整个应用。 向 app.config.globalProperties 中添加一些全局实例属性或方法 一个可能上述三种…

Element UI组件安装使用会了吗?

Element UI 是一套基于 Vue.js 构建的开源 UI 组件库&#xff0c;它提供了丰富且易于使用的 UI 组件&#xff0c;能够帮助开发者快速搭建企业级的页面。以下是详细的 Element UI 组件安装及使用步骤&#xff1a; 安装 Element UI 方法一&#xff1a;使用 npm 安装 适用于 No…

Qt程序设计-仪表盘自定义控件实例

本文讲解Qt仪器表盘自定义控件实例。 效果如下 创建仪表表盘类 #ifndef DIALPLATE_H #define DIALPLATE_H#include <QWidget> #include <QTimer> #include <QPainter> #include <QPen> #include <QDebug> #include <QtMath> #include &l…

程序员就业数据分析,需要掌握python哪些知识?

程序员就业数据分析是一项综合性的工作&#xff0c;涉及到多个方面的知识和技能。Python 是一种功能强大的编程语言&#xff0c;被广泛应用于数据分析领域。要进行程序员就业数据分析&#xff0c;你需要掌握一系列与 Python 相关的知识。 1. Python 基础知识 基本语法和数据类…

序列化-反序列化--json-xml-protoBuf

序列化和反序列化 数据在网络中传输需要按照一定的规范组成。这些规定的规范有json,xml,protobuf。 序列化 也就是说数据需要通过网络传输时&#xff0c;需要把数据转化为需要的传输格式&#xff0c;所以需要把需要传输的数据生成json或者xml或者protobuf语言格式文件&#…

【论文阅读】基于图像处理和卷积神经网络的板式换热器气泡识别与跟踪

Bubble recognizing and tracking in a plate heat exchanger by using image processing and convolutional neural network 基于图像处理和卷积神经网络的板式换热器气泡识别与跟踪 期刊信息&#xff1a;International Journal of Multiphase Flow 2021 期刊级别&#xff1a;…

IDEA中 @SpringBootApplication 多个注解无法引入依赖

终于解决了&#xff01;&#xff01;&#xff01; cd到报红项目的根目录&#xff0c;然后输入mvn idea:idea就行了。

2024022701-信息安全(二)——密码学

密码学的基本概念 密码学(Cryptology)&#xff1a; 研究信息系统安全保密的科学。 密码编码学(Cryptography)&#xff1a; 研究对信息进行编码,实现对信息的隐蔽。 密码分析学(Cryptanalytics) &#xff1a; 研究加密消息的破译或消息的伪造。 消息被称为明文(Plaintext)。 用…