OpenCV中的机器学习
(1)Bayesian,Normal Bayes Classifier(贝叶斯分类)
基于贝叶斯定理,假设特征之间相互独立(朴素贝叶斯假设)。通过计算每个类别在给定特征条件下的概率来进行分类。在训练过程中,统计每个类别中各特征的出现频率,从而估计类条件概率。预测时,依据贝叶斯公式算出样本属于各个类别的后验概率,将概率最大的类别作为预测结果。
cpp
#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main() {
// 准备训练数据
Mat trainingData = (Mat_<float>(5, 2) << 1, 1, 1, 2, 2, 2, 2, 3, 3, 3);
Mat labels = (Mat_<int>(5, 1) << 0, 0, 1, 1, 1);
// 创建贝叶斯分类器
Ptr<NormalBayesClassifier> model = NormalBayesClassifier::create();
// 训练模型
model->train(trainingData, ROW_SAMPLE, labels);
// 准备测试数据
Mat testData = (Mat_<float>(1, 2) << 2, 2);
// 预测
float response = model->predict(testData);
std::cout << "Predicted class: " << response << std::endl;
return 0;
}
(2)K-Nearest Neighbour Classifier(K-邻近算法)
KNN 是一种基于实例的学习算法。对于一个新的样本,它在训练数据集中找到 K 个与其距离最近的样本(通常使用欧氏距离等度量),然后根据这 K 个近邻样本的类别来决定新样本的类别。例如,若 K = 3,且这 3 个近邻中有 2 个属于类别 A,1 个属于类别 B,则新样本被归类为类别 A。
cpp
#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main() {
Mat trainingData = (Mat_<float>(5, 2) << 1, 1, 1, 2, 2, 2, 2, 3, 3, 3);
Mat labels = (Mat_<int>(5, 1) << 0, 0, 1, 1, 1);
// 创建KNN模型,K设为3
Ptr<KNearest> model = KNearest::create();
model->setDefaultK(3);
// 训练模型
model->train(trainingData, ROW_SAMPLE, labels);
Mat testData = (Mat_<float>(1, 2) << 2, 2);
// 预测
Mat results, neighbors;
float dist;
model->findNearest(testData, 3, results, neighbors, dist);
std::cout << "Predicted class: " << results.at<int>(0, 0) << std::endl;
return 0;
}
(3)SVM,Support Vector Machine(支持向量机)
SVM 旨在找到一个最优超平面,将不同类别的数据点尽可能分开,且使间隔最大化。对于线性可分的数据,可直接找到这样的超平面;对于线性不可分的数据,通过引入核函数将数据映射到高维空间,从而找到合适的超平面。
cpp
#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main() {
Mat trainingData = (Mat_<float>(5, 2) << 1, 1, 1, 2, 2, 2, 2, 3, 3, 3);
Mat labels = (Mat_<int>(5, 1) << 0, 0, 1, 1, 1);
// 创建SVM模型
Ptr<SVM> model = SVM::create();
model->setType(SVM::C_SVC);
model->setKernel(SVM::LINEAR);
// 训练模型
model->train(trainingData, ROW_SAMPLE, labels);
Mat testData = (Mat_<float>(1, 2) << 2, 2);
// 预测
float response = model->predict(testData);
std::cout << "Predicted class: " << response << std::endl;
return 0;
}
(4)Expectation-Maximization(EM算法)
EM 算法是一种迭代算法,用于含有隐变量的概率模型参数估计。它分为两个步骤:E 步(期望步骤)和 M 步(最大化步骤)。在 E 步中,根据当前估计的参数计算隐变量的期望;在 M 步中,基于 E 步得到的期望,最大化似然函数来更新参数。常用于聚类问题,如高斯混合模型(GMM)。
cpp
#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main() {
Mat data = (Mat_<float>(5, 2) << 1, 1, 1, 2, 2, 2, 2, 3, 3, 3);
int K = 2; // 聚类数
Mat labels;
Mat centers;
// 创建EM模型
Ptr<EM> em = EM::create();
em->setClustersNumber(K);
em->trainEM(data, labels, centers);
// 预测每个点所属的簇
Mat responsibilities;
em->predict2(data, responsibilities);
for (int i = 0; i < data.rows; ++i) {
int cluster = std::max_element(responsibilities.ptr<float>(i), responsibilities.ptr<float>(i) + K) - responsibilities.ptr<float>(i);
std::cout << "Point " << i << " belongs to cluster " << cluster << std::endl;
}
return 0;
}
(5)Decision Tree(决策树)
决策树是一种基于树结构进行决策的算法。它通过对数据特征的不断划分,构建出一个类似于流程图的树形结构。每个内部节点表示一个特征上的测试,分支表示测试输出,叶节点表示分类结果。例如在判断一个水果是苹果还是橙子时,可能首先根据颜色进行判断,如果颜色是红色,再根据形状进一步判断,逐步引导至最终的分类结果。
cpp
#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main() {
Mat trainingData = (Mat_<float>(5, 2) << 1, 1, 1, 2, 2, 2, 2, 3, 3, 3);
Mat labels = (Mat_<int>(5, 1) << 0, 0, 1, 1, 1);
// 创建决策树模型
Ptr<DecisionTree> model = DecisionTree::create();
model->setMaxDepth(3);
// 训练模型
model->train(trainingData, ROW_SAMPLE, labels);
Mat testData = (Mat_<float>(1, 2) << 2, 2);
// 预测
float response = model->predict(testData);
std::cout << "Predicted class: " << response << std::endl;
return 0;
}
(6)Random Trees Classifier(随机森林算法)
随机森林是一种集成学习算法,它构建多个决策树作为基学习器,并通过投票(分类问题)或平均(回归问题)等方式组合这些决策树的预测结果。在构建每棵决策树时,从原始数据集中有放回地随机抽取样本,同时随机选择部分特征进行划分。这样可以降低模型的方差,提高模型的稳定性和泛化能力。
cpp
#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main() {
Mat trainingData = (Mat_<float>(5, 2) << 1, 1, 1, 2, 2, 2, 2, 3, 3, 3);
Mat labels = (Mat_<int>(5, 1) << 0, 0, 1, 1, 1);
// 创建随机森林模型
Ptr<RTrees> model = RTrees::create();
model->setCVFolds(10);
// 训练模型
model->train(trainingData, ROW_SAMPLE, labels);
Mat testData = (Mat_<float>(1, 2) << 2, 2);
// 预测
float response = model->predict(testData);
std::cout << "Predicted class: " << response << std::endl;
return 0;
}
(7)Extremely Randomized Trees Classifier(绝对随机森林算法)
与随机森林类似,但在决策树的节点分裂上更加随机。在选择分裂特征和分裂点时,绝对随机森林不是像随机森林那样从随机子集里选择最优,而是完全随机地选择分裂点,这进一步增加了随机性,有可能降低模型的方差,但也可能导致偏差增加,需要权衡。
cpp
#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main() {
Mat trainingData = (Mat_<float>(5, 2) << 1, 1, 1, 2, 2, 2, 2, 3, 3, 3);
Mat labels = (Mat_<int>(5, 1) << 0, 0, 1, 1, 1);
// 创建绝对随机森林模型
Ptr<ERTrees> model = ERTrees::create();
model->setMaxDepth(3);
// 训练模型
model->train(trainingData, ROW_SAMPLE, labels);
Mat testData = (Mat_<float>(1, 2) << 2, 2);
// 预测
float response = model->predict(testData);
std::cout << "Predicted class: " << response << std::endl;
return 0;
}
(8)Boosted Tree Classifier(Boost树算法)
通过迭代的方式,每次训练一个新的基学习器(决策树)来纠正前一个基学习器的错误。前一个基学习器分类错误的数据在后续训练中会得到更多关注,使得后续学习器更专注于这些难分类的数据。最终将所有基学习器的预测结果进行加权组合,得到最终的预测结果。
#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main() {
Mat trainingData = (Mat_(5, 2) << 1, 1, 1, 2, 2, 2, 2, 3, 3, 3);
Mat labels = (Mat_(5, 1) << 0, 0, 1, 1, 1);
// 创建Boost树模型
Ptr<Boost> model = Boost::create();
model->setWeakCount(10);
// 训练模型
model->train(trainingData, ROW_SAMPLE, labels);
Mat testData = (Mat_<float>(1, 2) << 2, 2);
// 预测
float response = model->predict(testData);
std::cout << "Predicted class: " << response << std::endl;
return 0;
}
(9)Gradient Boosted Trees(梯度Boost树算法)
也是一种迭代的集成学习算法,每次新生成的树拟合的是之前所有树的预测结果与真实值之间的残差的梯度方向。通过这种方式逐步减小预测误差,不断提升模型的性能。它在回归和分类问题上都有很好的表现,并且对复杂的数据分布有较强的适应能力。
cpp
#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main() {
Mat trainingData = (Mat_<float>(5, 2) << 1, 1, 1, 2, 2, 2, 2, 3, 3, 3);
Mat labels = (Mat_<int>(5, 1) << 0, 0, 1, 1, 1);
// 创建梯度Boost树模型
Ptr<GBDT> model = GBDT::create();
model->setMaxDepth(3);
// 训练模型
model->train(trainingData, ROW_SAMPLE, labels);
Mat testData = (Mat_<float>(1, 2) << 2, 2);
// 预测
float response = model->predict(testData);
std::cout << "Predicted class: " << response << std::endl;
return 0;
}
(10)ANN,Artificial Neural Networks(人工神经网络)
由大量神经元相互连接组成,神经元之间通过权重传递信号,通过调整权重来学习数据中的模式和规律。典型的神经网络包括输入层、隐藏层和输出层。在训练过程中,通过前向传播计算预测值,然后通过反向传播计算误差并更新权重,使得预测值与真实值之间的误差不断减小。
cpp
#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main() {
Mat trainingData = (Mat_<float>(5, 2) << 1, 1, 1, 2, 2, 2, 2, 3, 3, 3);
Mat labels = (Mat_<int>(5, 1) << 0, 0, 1, 1, 1);
// 创建神经网络模型
Ptr<ANN_MLP> model = ANN_MLP::create();
Mat layerSizes = (Mat_<int>(3, 1) << 2, 5, 1);
model->setLayerSizes(layerSizes);
model->setActivationFunction(ANN_MLP::SIGMOID_SYM);
// 训练模型
model->train(trainingData, ROW_SAMPLE, labels);
Mat testData = (Mat_<float>(1, 2) << 2, 2);
Mat result;
// 预测
model->predict(testData, result);
std::cout << "Predicted value: " << result.at<float>(0, 0) << std::endl;
return 0;
}