【opencv】示例-points_classifier.cpp 使用不同机器学习算法在二维空间中对点集进行分类...

94d0054ae0ba0d7ff35aadbf072116ea.png

4db1625a5a1856eaa4e9fdee0c7e235d.png

bdd39b4a84bdd382b384c669847bc528.png

#include "opencv2/core.hpp" // 包含OpenCV核心功能的文件
#include "opencv2/imgproc.hpp" // 包含OpenCV图像处理功能的文件
#include "opencv2/ml.hpp" // 包含OpenCV机器学习模块的文件
#include "opencv2/highgui.hpp" // 包含OpenCV用户界面组件的文件


#include <stdio.h>


using namespace std; // 使用标准命名空间
using namespace cv; // 使用OpenCV命名空间
using namespace cv::ml; // 使用OpenCV机器学习命名空间


const Scalar WHITE_COLOR = Scalar(255,255,255); // 定义一个常量表示白色
const string winName = "points"; // 窗口名
const int testStep = 5; // 测试步长


Mat img, imgDst; // 定义两个图像矩阵,img为原图,imgDst为显示结果用
RNG rng; // 随机数生成器


vector<Point> trainedPoints; // 存储训练用的点
vector<int> trainedPointsMarkers; // 存储训练点所属的分类标记
const int MAX_CLASSES = 2; // 最大分类数
vector<Vec3b> classColors(MAX_CLASSES); // 存储每个分类的颜色
int currentClass = 0; // 当前选择的分类
vector<int> classCounters(MAX_CLASSES); // 存储每个分类的计数器


// 定义一些预处理器标志以确定哪些分类器将会被使用
#define _NBC_ 1 // 正态贝叶斯分类器
#define _KNN_ 1 // K最近邻分类器
#define _SVM_ 1 // 支持向量机
#define _DT_  1 // 决策树
#define _BT_  1 // ADA提升
#define _GBT_ 0 // 梯度提升树
#define _RF_  1 // 随机森林
#define _ANN_ 1 // 人工神经网络
#define _EM_  1 // 期望最大化


// 鼠标事件回调函数
static void on_mouse( int event, int x, int y, int /*flags*/, void* )
{
    if( img.empty() )
        return;


    int updateFlag = 0; // 更新标志


    if( event == EVENT_LBUTTONUP ) // 当鼠标左键松开时
    {
        trainedPoints.push_back( Point(x,y) ); // 添加一个点到训练集中
        trainedPointsMarkers.push_back( currentClass ); // 为这个点标记当前的类别
        classCounters[currentClass]++; // 相应类别的计数器加一
        updateFlag = true; // 设置更新标志为真
    }


    // 绘制
    if( updateFlag )
    {
        img = Scalar::all(0); // 将图像设置为黑色


        // 绘制点
        for( size_t i = 0; i < trainedPoints.size(); i++ )
        {
            Vec3b c = classColors[trainedPointsMarkers[i]]; // 获取点的颜色
            circle( img, trainedPoints[i], 5, Scalar(c), -1 ); // 在图像上用这个颜色绘制一个圆
        }


        imshow( winName, img ); // 显示图像
    }
}


// 准备训练样本的辅助函数
static Mat prepare_train_samples(const vector<Point>& pts)
{
    Mat samples;
    Mat(pts).reshape(1, (int)pts.size()).convertTo(samples, CV_32F); // 将Point集合转换为Mat格式并改变数据类型
    return samples;
}


// 准备训练数据的辅助函数
static Ptr<TrainData> prepare_train_data()
{
    Mat samples = prepare_train_samples(trainedPoints); // 准备样本
    return TrainData::create(samples, ROW_SAMPLE, Mat(trainedPointsMarkers)); // 创建训练数据对象
}


// 使用模型进行预测并绘制结果的辅助函数
static void predict_and_paint(const Ptr<StatModel>& model, Mat& dst)
{
    Mat testSample( 1, 2, CV_32FC1 ); // 创建一个包含两个float类型数值的测试样本
    for( int y = 0; y < img.rows; y += testStep ) // 按步长遍历图像所有的y坐标
    {
        for( int x = 0; x < img.cols; x += testStep ) // 按步长遍历图像所有的x坐标
        {
            testSample.at<float>(0) = (float)x; // 设置样本x值
            testSample.at<float>(1) = (float)y; // 设置样本y值


            int response = (int)model->predict( testSample ); // 使用模型进行预测
            dst.at<Vec3b>(y, x) = classColors[response]; // 根据预测结果上色
        }
    }
}


// 下面的一系列#if预处理器指令是为了在最终的程序中包含或者排除某些分类器的相关代码


#if _NBC_
// 使用正态贝叶斯分类器找出决策边界
static void find_decision_boundary_NBC()
{
    // 学习分类器
    Ptr<NormalBayesClassifier> normalBayesClassifier = StatModel::train<NormalBayesClassifier>(prepare_train_data());
    // 预测并绘制决策边界
    predict_and_paint(normalBayesClassifier, imgDst);
}
#endif


#if _KNN_
// 使用K最近邻分类器找出决策边界,并设置K值
static void find_decision_boundary_KNN( int K )
{
    // 创建KNN对象
    Ptr<KNearest> knn = KNearest::create();
    // 设置K值
    knn->setDefaultK(K);
    // 设置为分类模式
    knn->setIsClassifier(true);
    // 训练模型
    knn->train(prepare_train_data());
    // 预测并绘制决策边界
    predict_and_paint(knn, imgDst);
}
#endif


#if _SVM_
// 使用支持向量机找出决策边界,并设置错误惩罚参数C
static void find_decision_boundary_SVM( double C )
{
    // 创建SVM对象
    Ptr<SVM> svm = SVM::create();
    // 设置SVM类型为C-SVC
    svm->setType(SVM::C_SVC);
    // 设置核函数为多项式核
    svm->setKernel(SVM::POLY); // 也可以选用线性核SVM::LINEAR;
    // 设置多项式核参数degree
    svm->setDegree(0.5);
    // 设置核函数参数gamma
    svm->setGamma(1);
    // 设置核函数参数coef0
    svm->setCoef0(1);
    // 设置SVM参数Nu
    svm->setNu(0.5);
    // 设置SVM参数P
    svm->setP(0);
    // 设置训练算法的终止条件
    svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 1000, 0.01));
    // 设置错误惩罚参数C
    svm->setC(C);
    // 训练模型
    svm->train(prepare_train_data());
    // 预测并绘制决策边界
    predict_and_paint(svm, imgDst);


    // 绘制支持向量
    Mat sv = svm->getSupportVectors();
    for( int i = 0; i < sv.rows; i++ )
    {
        const float* supportVector = sv.ptr<float>(i);
        circle( imgDst, Point(saturate_cast<int>(supportVector[0]),saturate_cast<int>(supportVector[1])), 5, Scalar(255,255,255), -1 );
    }
}
#endif


#if _DT_
// 使用决策树找出决策边界
static void find_decision_boundary_DT()
{
    // 创建决策树对象
    Ptr<DTrees> dtree = DTrees::create();
    // 设置决策树最大深度
    dtree->setMaxDepth(8);
    // 设置节点最小样本数
    dtree->setMinSampleCount(2);
    // 设置是否使用代理分割
    dtree->setUseSurrogates(false);
    // 设置交叉验证折数
    dtree->setCVFolds(0); // 0表示不进行交叉验证
    // 设置是否使用1SE规则
    dtree->setUse1SERule(false);
    // 设置是否修剪被减枝的决策树
    dtree->setTruncatePrunedTree(false);
    // 训练模型
    dtree->train(prepare_train_data());
    // 预测并绘制决策边界
    predict_and_paint(dtree, imgDst);
}
#endif


#if _BT_
// 使用提升树算法找出决策边界
static void find_decision_boundary_BT()
{
    // 创建提升树对象
    Ptr<Boost> boost = Boost::create();
    // 设置提升类型
    boost->setBoostType(Boost::DISCRETE);
    // 设置弱分类器数量
    boost->setWeakCount(100);
    // 设置权重修剪率
    boost->setWeightTrimRate(0.95);
    // 设置最大深度
    boost->setMaxDepth(2);
    // 设置是否使用代理分割
    boost->setUseSurrogates(false);
    // 设置类别先验概率
    boost->setPriors(Mat());
    // 训练模型
    boost->train(prepare_train_data());
    // 预测并绘制决策边界
    predict_and_paint(boost, imgDst);
}
#endif


#if _GBT_
// 使用梯度提升树算法找出决策边界
static void find_decision_boundary_GBT()
{
    // 设置GBT模型参数
    GBTrees::Params params( GBTrees::DEVIANCE_LOSS, // 损失函数类型
                         100, // 弱分类器数量
                         0.1f, // 收缩率
                         1.0f, // 子采样比例
                         2, // 最大深度
                         false // 是否使用代理分割
                         );


    // 创建梯度提升树对象
    Ptr<GBTrees> gbtrees = StatModel::train<GBTrees>(prepare_train_data(), params);
    // 预测并绘制决策边界
    predict_and_paint(gbtrees, imgDst);
}
#endif


#if _RF_
// 使用随机森林算法找出决策边界
static void find_decision_boundary_RF()
{
    // 创建随机森林对象
    Ptr<RTrees> rtrees = RTrees::create();
    // 设置最大深度
    rtrees->setMaxDepth(4);
    // 设置节点最小样本数
    rtrees->setMinSampleCount(2);
    // 设置回归精度
    rtrees->setRegressionAccuracy(0.f);
    // 设置是否使用代理分割
    rtrees->setUseSurrogates(false);
    // 设置类别数量
    rtrees->setMaxCategories(16);
    // 设置类别先验概率
    rtrees->setPriors(Mat());
    // 设置是否计算变量重要性
    rtrees->setCalculateVarImportance(false);
    // 设置活跃变量数量
    rtrees->setActiveVarCount(1);
    // 设置训练算法的终止条件
    rtrees->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 5, 0));
    // 训练模型
    rtrees->train(prepare_train_data());
    // 预测并绘制决策边界
    predict_and_paint(rtrees, imgDst);
}
#endif


#if _ANN_
// 使用人工神经网络找出决策边界
static void find_decision_boundary_ANN( const Mat& layer_sizes )
{
    // 创建类别标签矩阵
    Mat trainClasses = Mat::zeros( (int)trainedPoints.size(), (int)classColors.size(), CV_32FC1 );
    for( int i = 0; i < trainClasses.rows; i++ )
    {
        trainClasses.at<float>(i, trainedPointsMarkers[i]) = 1.f; // 对应类别置为1
    }


    // 准备训练样本
    Mat samples = prepare_train_samples(trainedPoints);
    // 创建训练数据对象
    Ptr<TrainData> tdata = TrainData::create(samples, ROW_SAMPLE, trainClasses);


    // 创建人工神经网络对象
    Ptr<ANN_MLP> ann = ANN_MLP::create();
    // 设置网络层大小
    ann->setLayerSizes(layer_sizes);
    // 设置激活函数
    ann->setActivationFunction(ANN_MLP::SIGMOID_SYM, 1, 1);
    // 设置训练算法的终止条件
    ann->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 300, FLT_EPSILON));
    // 设置训练方法,这里使用反向传播算法
    ann->setTrainMethod(ANN_MLP::BACKPROP, 0.001);
    // 训练模型
    ann->train(tdata);
    // 预测并绘制决策边界
    predict_and_paint(ann, imgDst);
}
#endif


#if _EM_
// 使用期望最大化算法找出决策边界
static void find_decision_boundary_EM()
{
    img.copyTo(imgDst); // 将当前图像复制给目标图像


    Mat samples = prepare_train_samples(trainedPoints); // 准备训练样本


    int i, j, nmodels = (int)classColors.size(); // 分类数量
    vector<Ptr<EM>> em_models(nmodels); // 存储每个类别对应的EM模型
    Mat modelSamples;


    // 遍历所有分类来训练EM模型
    for (i = 0; i < nmodels; i++)
    {
        const int componentCount = 3; // 每个模型的分量数


        modelSamples.release(); // 释放模型样本空间
        // 提取当前类别的所有样本
        for (j = 0; j < samples.rows; j++)
        {
            if (trainedPointsMarkers[j] == i)
                modelSamples.push_back(samples.row(j));
        }


        // 训练模型
        if (!modelSamples.empty()) // 如果当前类别有样本
        {
            Ptr<EM> em = EM::create(); // 创建EM模型
            em->setClustersNumber(componentCount); // 设置聚类数量
            em->setCovarianceMatrixType(EM::COV_MAT_DIAGONAL); // 设置协方差类型为对角线
            em->trainEM(modelSamples, noArray(), noArray(), noArray()); // 训练EM模型
            em_models[i] = em; // 存储训练好的模型
        }
    }


    // 使用贝叶斯分类器对坐标平面的点进行分类
    // y(x) = arg max_i=1_modelsCount likelihoods_i(x)
    Mat testSample(1, 2, CV_32FC1); // 测试样本
    Mat logLikelihoods(1, nmodels, CV_64FC1, Scalar(-DBL_MAX)); // 存储每个样本的概率


    // 遍历图像上的每个点
    for (int y = 0; y < img.rows; y += testStep) 
    {
        for (int x = 0; x < img.cols; x += testStep)
        {
            testSample.at<float>(0) = (float)x;
            testSample.at<float>(1) = (float)y;


            for (i = 0; i < nmodels; i++)
            {
                if (!em_models[i].empty()) // 如果EM模型有效
                    // 计算测试样本的对数似然概率
                    logLikelihoods.at<double>(i) = em_models[i]->predict2(testSample, noArray())[0];
            }
            Point maxLoc;
            // 找到概率最大的类别
            minMaxLoc(logLikelihoods, 0, 0, 0, &maxLoc);
            // 将图像对应位置染成最大概率类别的颜色
            imgDst.at<Vec3b>(y, x) = classColors[maxLoc.x];
        }
    }
}
#endif




int main()
{
    cout << "Use:" << endl
         << "  key '0' .. '1' - switch to class #n" << endl
         << "  left mouse button - to add new point;" << endl
         << "  key 'r' - to run the ML model;" << endl
         << "  key 'i' - to init (clear) the data." << endl << endl;


    cv::namedWindow("points", 1); // 创建一个名为"points"的窗口
    img.create(480, 640, CV_8UC3); // 创建一个大小为480x640的图像
    imgDst.create(480, 640, CV_8UC3); // 创建一个用于显示结果的图像


    imshow("points", img); // 显示原始图像
    setMouseCallback("points", on_mouse); // 设置鼠标回调函数,response to mouse events


    // 初始化两个分类的颜色,第一个分类颜色为绿色,第二个分类颜色为红色
    classColors[0] = Vec3b(0, 255, 0);
    classColors[1] = Vec3b(0, 0, 255);


    // 主循环
    for (;;)
    {
        char key = (char)waitKey(); // 等待按键


        if (key == 27) break; // 如果按键是ESC,退出程序


        if (key == 'i') // 初始化
        {
            img = Scalar::all(0); // 清除图像


            trainedPoints.clear(); // 清除训练点
            trainedPointsMarkers.clear(); // 清除训练点标记
            classCounters.assign(MAX_CLASSES, 0); // 重置类别计数器


            imshow(winName, img); // 显示清除后的图像
        }


        if (key == '0' || key == '1') // 切换类别
        {
            currentClass = key - '0'; // 根据按键设置当前类别
        }


        if (key == 'r') // 运行机器学习模型
        {
            double minVal = 0;
            minMaxLoc(classCounters, &minVal, 0, 0, 0); // 检查每个类别至少有一个点
            if (minVal == 0)
            {
                printf("each class should have at least 1 point\n"); // 否则提示并继续循环
                continue;
            }
            img.copyTo(imgDst); // 将图像复制到目标图像上
#if _NBC_
            find_decision_boundary_NBC(); // 执行NBC算法找决策边界
            imshow("NormalBayesClassifier", imgDst); // 显示NBC的结果
#endif
#if _KNN_
// 使用K-最近邻算法找出决策边界,这里展示了两种不同的K值
            find_decision_boundary_KNN(3); // 使用k值为3来找到决策边界
            imshow("kNN", imgDst); // 显示k值为3的结果


            find_decision_boundary_KNN(15); // 使用k值为15来找到决策边界
            imshow("kNN2", imgDst); // 显示k值为15的结果
#endif


#if _SVM_
// 使用支持向量机算法找出决策边界
            find_decision_boundary_SVM(1); // 使用C值为1来找到决策边界
            imshow("classificationSVM1", imgDst); // 显示C值为1的结果


            find_decision_boundary_SVM(10); // 使用C值为10来找到决策边界
            imshow("classificationSVM2", imgDst); // 显示C值为10的结果
#endif


#if _DT_
// 使用决策树算法找出决策边界
            find_decision_boundary_DT(); // 执行决策树算法找到决策边界
            imshow("DT", imgDst); // 显示决策树的结果
#endif


#if _BT_
// 使用提升树算法找出决策边界
            find_decision_boundary_BT(); // 执行提升树算法找到决策边界
            imshow("BT", imgDst); // 显示提升树的结果
#endif


#if _GBT_
// 使用梯度提升树算法找出决策边界
            find_decision_boundary_GBT(); // 执行梯度提升树算法找到决策边界
            imshow("GBT", imgDst); // 显示梯度提升树的结果
#endif


#if _RF_
// 使用随机森林算法找出决策边界
            find_decision_boundary_RF(); // 执行随机森林算法找到决策边界
            imshow("RF", imgDst); // 显示随机森林的结果
#endif


#if _ANN_
// 使用人工神经网络算法找出决策边界
            Mat layer_sizes1(1, 3, CV_32SC1); // 设置神经网络的层数和每层的节点数
            layer_sizes1.at<int>(0) = 2; // 输入层节点数
            layer_sizes1.at<int>(1) = 5; // 隐藏层节点数
            layer_sizes1.at<int>(2) = (int)classColors.size(); // 输出层节点数,即类别数
            find_decision_boundary_ANN(layer_sizes1); // 执行人工神经网络算法找到决策边界
            imshow("ANN", imgDst); // 显示人工神经网络的结果
#endif
#if _EM_
            // 执行EM算法找决策边界
            find_decision_boundary_EM();
            // 显示EM算法的结果
            imshow("EM", imgDst);
#endif
        }
    }


    return 0; // 程序结束
}

这段代码实现了一个简单的机器视觉和机器学习应用程序。其主要功能是在图形用户界面中用鼠标标记出不同的类别点,然后通过多种机器学习模型(如正态贝叶斯分类器、K最近邻分类器、支持向量机等),学习这些点的分布规律,并预测整个图像坐标面中每个点的类别,并进行着色以区分不同类别。

代码的核心部分包括鼠标回调函数(on_mouse),它处理用户的鼠标事件,根据用户点击添加新的类别点;数据准备辅助函数,用于将标记的点转换为训练模型所需的格式;模型训练和预测函数,包括每个分类器独立的训练和预测逻辑;以及主函数,它负责初始化应用程序界面、处理用户输入并触发机器学习模型的训练和预测。

这段代码展示了多个不同的机器学习算法在机器视觉和机器人技术应用程序中确定决策边界的方法。每个#if块介绍了如何使用一个特定的算法来训练一个模型用于分类,并预测图像上每个像素点的类别,并用不同的颜色来表示不同类别的决策区域。具体来说,包括:

  1. 使用正态贝叶斯分类器(NBC)确定决策边界。

  2. 使用K最邻近算法(KNN)确定决策边界,K值可以调整。

  3. 使用支持向量机(SVM)确定决策边界,其中C为错误项的惩罚系数。

  4. 使用决策树(DT)来确定决策边界。

  5. 使用提升树(Boosted Trees, BT)来确定决策边界。

  6. 使用梯度提升树(Gradient Boosted Trees, GBT)来确定决策边界。

  7. 使用随机森林(Random Forest, RF)来确定决策边界。

  8. 使用人工神经网络(Artificial Neural Network, ANN)来确定决策边界,其中层的大小可以调整,通常由输入层、一个或多个隐藏层和输出层构成。

9. 期望最大化(Expectation Maximization, EM)算法在寻找决策边界的实现方式。EM是一种迭代优化算法,用于参数估计,特别适合处理有隐变量的概率模型。它通常用于聚类或者潜在变量模型的估计。在find_decision_boundary_EM函数中,这个算法先是为每个类别训练了一个EM模型。接着通过遍历图像上的每个像素,计算该像素属于每个模型的概率,然后选择概率最大的模型对应的类别,为该像素分配颜色。

这些算法通常用于机器视觉中的模式识别、分类任务或者机器人路径规划中的决策制定等应用场景。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MIT6.S081】Lab3: page tables(详细解答版)

实验内容网址&#xff1a;https://xv6.dgs.zone/labs/requirements/lab3.html 本实验的代码分支&#xff1a;https://gitee.com/dragonlalala/xv6-labs-2020/tree/pgtbl2/ Print a page table 关键点&#xff1a;递归、三级页表 思路&#xff1a; 用上图来解释三级页表的原理最…

RISC-V技术变革:一颗芯片,CPU与GPU合二为一

一颗万能的RISC-V芯片: 将CPU和GPU整合到一个核中 X-Silicon 推出创新的 RISC-V 芯片架构,将 CPU、矢量功能和 GPU 加速无缝集成。这种开源混合芯片专为多功能工作负载而设计,包括人工智能,旨在通过高效处理提升性能。 革命性的 CPU/GPU 混合处理器全新的 RISC-V CPU/GPU 混…

【前端面试3+1】12 toktn验证过程、面向对象特性、webpack和vite的区别、【字符串中的第一个唯一字符】

一、token验证过程 用户登录&#xff1a;用户提供用户名和密码进行登录。服务器验证&#xff1a;服务器接收到用户提供的用户名和密码&#xff0c;进行验证。生成token&#xff1a;如果用户名和密码验证通过&#xff0c;服务器会生成一个token&#xff0c;通常包含一些加密的信…

从 iPhone 上的短信中恢复已删除的图片的可靠方法

您可能在浏览消息聊天时不小心删除了一些文本和照片。事实上&#xff0c;如果这些消息对你来说意义重大&#xff0c;那对你来说可能会很麻烦。当发生意外情况时&#xff0c;您可能不想恢复整个聊天&#xff0c;而是恢复其中的附件。 好了&#xff0c;这篇文章主要是讲如何灵活…

关于故障诊断的一些事-答知乎问(四)

利用深度学习模型进行机械故障诊断技术的难点是什么&#xff1f; 除了严格的可解释性之外&#xff0c;还有 1.很多机械设备经常运行在转速多变、载荷冲击、噪声淹没的恶劣工作环境之下&#xff0c;振动监测信号内包含了多种故障频率成分和背景噪声信息&#xff0c;是一种非常…

【C语言基础】:预处理详解(一)

文章目录 一、预定义符号二、#define定义常量三、#define定义宏四、带有副作用的宏参数五、宏替换的规则 一、预定义符号 在C语言中设置了许多的预定义符号&#xff0c;这些预定义符号是可以直接使用的&#xff0c;预定义符号也是在预处理阶段进行处理的。 常见的预定义符号&…

【系统分析师】计算机组成与体系架构

文章目录 1、编码及浮点数运算2、flynn分类法3、CISC和 RISC4、流水线技术5、存储技术5.1层次化存储结构5.2 Cache5.2.1 cache页面淘汰5.2.2 cache的读写 5.3 主存5.3.1主存编址5.3.2 磁盘 5.4 总线 6、校验码7、系统可靠性计算7.1可靠性指标7.2 串联系统与并联系统7.3性能指标…

Vue3——html-doc-ja(html导出为word的js库)

一、下载 官方地址 html-doc-js - npm npm install html-doc-js 二、使用方法 // 使用页面中引入 import exportWord from html-doc-js// 配置项以及实现下载方法 const wrap document.getElementById(test)const config {document:document, //默认当前文档的document…

如何将三方库集成到hap包中——通过IDE集成非cmake方式构建的C/C++三方库

简介 DevEco Studio(简称IDE)目前只支持cmake构建方式&#xff0c;对于非cmake构建方式的三方库需要通过IDE工具集成的话&#xff0c;我们需要对原生库编写一个cmake的构建脚本。本文通过tinyxpath三方库为例介绍如何在IDE上移植一个非cmake构建方式的三方库。 cmake构建脚本…

酷得智能 无人机方案开发

东莞市酷得智能科技有限公司&#xff0c;是一家专业的技术服务公司&#xff0c;致力于为各类智能硬件提供高效、稳定、安全的底层驱动解决方案。拥有一支经验丰富、技术精湛的团队&#xff0c;能够为客户提供全方位的底层驱动开发服务。 无人机功能介绍&#xff1a; 1、自动跟…

字符和字符串操作函数总结

索引 一 . 字符操作函数1. 字符分类函数2. 字符转换函数 二 . 字符串操作函数长度不受限制的字符串操作函数1. strcpy函数的使用和模拟实现2. strcat函数的使用和模拟实现3. strcmp函数的使用和模拟实现 长度受限制的字符串操作函数1. strncpy函数的使用2. strncat函数的使用3.…

字符函数strlen、strcpy、strcat、strcmp、strstr、strtok、 strerror和perror函数

目录 1、strlen函数 strlen函数的模拟实现 2、strcpy函数 strcpy函数的模拟实现 strncpy函数 strncpy函数的模拟实现 3、srtcat函数 strcat函数的模拟实现 strncat函数 strncat函数的模拟实现 4、strcmp函数 strcmp函数的模拟实现 strncmp函数 5、strstr函数 st…

anaconda创建了虚拟python环境,且安装了pytorch,但是pycharm中import torch运行时报错

报错如下&#xff1a; C:\Users\tashi\.conda\envs\test1\python.exe D:\project\python\transformer\main.py C:\Users\tashi\.conda\envs\test1\lib\site-packages\numpy\__init__.py:127: UserWarning: mkl-service package failed to import, therefore Intel(R) MKL init…

AI虽强,搜索引擎仍不可或缺

AI 领域正以前所未有的速度发展&#xff0c;大模型的发布变得愈发频繁&#xff0c;模型的规模也在持续扩大。如今&#xff0c;大模型的起点已经攀升至数十亿参数&#xff08;数十 B&#xff0c;B 是 Billion 的简写&#xff0c;10 亿&#xff09;&#xff0c;其功能之广泛&…

二、Python接口自动化fixture和conftest

1、fixture详解 fixture概念fixture是 pytest 用于将测试前后进行预备、清理工作的代码处理机制。 fixture相对于setup和teardown来说有以下几点优势: • fixure命名更加灵活&#xff0c;局限性比较小 • conftest.py 配置里面可以实现数据共享&#xff0c;不需要import就能自…

嵌入式sqlite3交叉编译移植

操作系统:Ubuntu20.04 下载sqlite3代码,下载版本3.30.00 wget https://www.sqlite.org/2019/sqlite-amalgamation-3300000.zip 或者https://download.csdn.net/download/benico/89127678 为什么下载amalgamation版本,不下载autoconf版本? 根据我的编译实验,同版本sql…

错题记录-华为海思

华为 海思数字芯片 参考 &#xff1a;FPGA开发/数字IC笔试系列(5) 华为海思IC笔试解析 FPGA开发/数字IC笔试系列(6) 华为海思IC笔试解析 SystemVerilog Function与Task的区别 $readmemh与$readmemb这两个系统任务是用来从指定文件中读取数据到寄存器数组或者RAM、ROM中。除了…

stm32与esp8266WIFI模块

硬件介绍 WIFI模块ESP-01S 使用AT指令控制1-ESP8266-AT指令初试化及部分基础知识_ch_pd-CSDN博客 项目需求 通过ESP-01SWIFI模块控制LED状态模拟插座 串口1用于与ESP8266通讯&#xff0c;串口2连接PC&#xff0c;用于打印log&#xff0c;查看系统状态 项目接线 将WIFI模块的…

LLM大语言模型微调方法和技术汇总

本文详细介绍了机器学习中的微调技术&#xff0c;特别是在预训练模型上进行微调的方法和技术。文章首先解释了什么是微调&#xff0c;即在预训练模型的基础上&#xff0c;通过特定任务的数据进行有监督训练&#xff0c;以提高模型在该任务上的性能。随后&#xff0c;详细介绍了…

Sonatype Nexus 服务器迁移

因为服务器的升级和调整&#xff0c;有时候会对安装 Sonatype Nexus 的服务器进行迁移到新服务器上。 从技术架构上来说&#xff0c;Sonatype Nexus 我们使用的是 AWS 的存储&#xff0c;所以我们并不需要拷贝大量的数据。 文件夹结构 在备份和恢复之前&#xff0c;我们需要…