【opencv】dnn示例-person_reid.cpp 人员识别(ReID,Re-Identification)系统

news2024/10/5 19:13:20

ReID(Re-Identification,即对摄像机视野外的人进行再识别)

f9ead194adfdb30e720ade283ef6cef5.png

d594c9e286ac15fa87e3f84fb95396d0.jpeg

0030_c1_f0056923.jpg

638af75a1984c8bf50ed10b1c6474530.jpeg

0042_c5_f0068994.jpg

186d15dca87d1f2cc30c77dd3ebd897c.jpeg

0056_c8_f0017063.jpg

以上为输出结果:result文件夹下

7140678ac74852f928ccc7ef4e27e897.png

bb29871aeb8a18c2938ac16c17b4f834.png

galleryLIst.txt

f1b1f73036d89a226fd45edb39d3c186.png

676c1be6abac50d39fde5bc7ca9c4cce.png

queryList.txt

模型下载:

8d0a2547f7d87d33484c41c645623bff.png

https://github.com/ReID-Team/ReID_extra_testdata/tree/main
https://drive.google.com/drive/folders/1wFGcuolSzX3_PqNKb4BAV3DNac7tYpc2

6424a37576095e249f7763a2446c2c11.png

这段代码是一个使用OpenCV库实现的人员识别(ReID,Re-Identification)系统。程序的主要功能是用于处理图像数据,根据查询图片(queries)识别并匹配图库中(gallery)的图片

首先,导入所需的头文件,包括标准输入输出(iostream)、文件流(fstream),以及OpenCV库中的图像处理(imgproc)、图像显示(highgui)和深度神经网络(dnn)相关的模块。

定义命令行参数,并使用OpenCV的CommandLineParser类来解析输入参数。参数包括模型文件路径、查询图像列表路径、图库图像列表路径、批次大小、输入图像调整大小的高和宽、可视化时显示的最多图库图像数(topk)、可视化结果保存路径、计算后端和目标计算设备的设置。

接下来定义一个cv::reid命名空间,包含一系列函数:

  • preprocess:预处理函数,对读入的图像进行标准化处理,按照给定的均值和标准差进行缩放。

  • normalization:特征归一化函数,将特征向量转换为单位向量。

  • extractFeatures:特征提取函数,从图像列表中批量读取图像,进行预处理后输入神经网络提取特征。

  • getNames:获取图像名单函数,从存储图像路径的文件中读取图像名称。

  • similarity:计算相似度函数,通过点积操作得出两个特征向量的相似度。

  • getTopK:选取TopK函数,对每一个查询特征,计算与所有图库特征的相似度,并排序选取最相似的K个结果。

  • addBorder:添加边框函数,给图像添加边框。

  • drawRankList:绘制排名列表函数,将查询图像和它的TopK相似图库图像绘制在一起进行可视化。

  • visualization:可视化函数,将所有查询结果进行可视化并保存到指定目录。

最后,main函数是程序的入口点,首先解析命令行参数,然后读取查询和图库图像的文件路径。使用readNet函数读取训练好的网络模型,并设置计算后端和设备。提取查询和图库图像的特征,并计算TopK结果。最后,对结果进行可视化和存储。

简单总结,该代码定义了一个基于OpenCV的人员重识别系统,可以读取图像,提取特征,并通过计算相似度来匹配查询图像与图库中的图像,最后可视化输出匹配结果。使用了OpenCV库中的深度学习模块和图像处理模块,以及标准的归一化和相似度计算方法来实现该功能。

// 以下是用于行人重识别(ReID)的基础模型和示例输入的下载地址:
// https://github.com/ReID-Team/ReID_extra_testdata


// 行人重识别(ReID)基础模型和示例的作者信息:
// Xing Sun <winfredsun@tencent.com>
// Feng Zheng <zhengf@sustech.edu.cn>
// Xinyang Jiang <sevjiang@tencent.com>
// Fufu Yu <fufuyu@tencent.com>
// Enwei Zhang <miyozhang@tencent.com>


// 版权信息
// Copyright (C) 2020-2021, Tencent.
// Copyright (C) 2020-2021, SUSTech.


#include <iostream> // 引入IO流库,用于数据输入输出
#include <fstream>  // 引入文件流库,用于文件操作


#include <opencv2/imgproc.hpp> // 引入OpenCV图像处理头文件
#include <opencv2/highgui.hpp> // 引入OpenCV GUI头文件
#include <opencv2/dnn.hpp>     // 引入OpenCV深度学习模块头文件


using namespace cv;          // 使用cv命名空间
using namespace cv::dnn;     // 使用cv::dnn命名空间


// 定义命令行参数解析所需的关键词参数
const char* keys =
"{help    h  |                 | show help message}"  // 帮助信息
"{model   m  |    youtu_reid_baseline_lite.onnx       | network model}"  // 网络模型
"{query_list q |    ReID_extra_testdata/queryList.txt     | list of query images}"  // 查询图像列表
"{gallery_list g |   ReID_extra_testdata/galleryList.txt    | list of gallery images}"  // 画廊图像列表
"{batch_size | 32              | batch size of each inference}"  // 每次推理的批处理大小
"{resize_h   | 256             | resize input to specific height.}"  // 输入图像调整到特定的高度
"{resize_w   | 128             | resize input to specific width.}"  // 输入图像调整到特定的宽度
"{topk k     | 5               | number of gallery images showed in visualization}"  // 可视化展示中画像的数量
"{output_dir |result       | path for visualization(it should be existed)}"  // 可视化结果的保存路径(必须已存在)
"{backend b  | 5               | choose one of computation backends: "
"0: automatically (by default), "  // 计算后端选项:默认自动选择
"1: Halide language (http://halide-lang.org/), "  // Halide语言后端
"2: Intel's Deep Learning Inference Engine (https://software.intel.com/openvino-toolkit), "  // 英特尔深度学习推理引擎后端
"3: OpenCV implementation, "  // OpenCV实现后端
"4: VKCOM, "  // VKCOM后端
"5: CUDA }"  // CUDA后端
"{target  t  | 6                | choose one of target computation devices: "
"0: CPU target (by default), "  // 计算设备选项:默认使用CPU
"1: OpenCL, "  // 使用OpenCL
"2: OpenCL fp16 (half-float precision), "  // 使用OpenCL半精度浮点数
"4: Vulkan, "  // 使用Vulkan
"6: CUDA, "  // 使用CUDA
"7: CUDA fp16 (half-float preprocess) }";  // 使用CUDA半精度预处理


// OpenCV和重识别命名空间内的处理函数
namespace cv{
namespace reid{


// 预处理图像的函数,将图像数据进行归一化处理
static Mat preprocess(const Mat& img)
{
    const double mean[3] = {0.485, 0.456, 0.406}; // 定义三个通道的均值
    const double std[3] = {0.229, 0.224, 0.225};  // 定义三个通道的标准差
    Mat ret = Mat(img.rows, img.cols, CV_32FC3);  // 创建一个新的Mat对象来存放处理后的图像
    for (int y = 0; y < ret.rows; y ++)          // 遍历图像的行
    {
        for (int x = 0; x < ret.cols; x++)       // 遍历图像的列
        {
            for (int c = 0; c < 3; c++)          // 遍历图像的通道
            {
                // 进行通道值的归一化处理,并将结果存储在新的Mat对象中
                ret.at<Vec3f>(y,x)[c] = (float)((img.at<Vec3b>(y,x)[c] / 255.0 - mean[2 - c]) / std[2 - c]);
            }
        }
    }
    return ret; // 返回处理后的图像
}


// 特征向量归一化的函数
static std::vector<float> normalization(const std::vector<float>& feature)
{
    std::vector<float> ret; // 创建一个用于存储归一化后特征的向量
    float sum = 0.0;        // 初始化求和变量
    for(int i = 0; i < (int)feature.size(); i++) // 遍历特征向量的元素
    {
        sum += feature[i] * feature[i]; // 计算L2范数的平方累积
    }
    sum = sqrt(sum); // 计算L2范数
    for(int i = 0; i < (int)feature.size(); i++) // 再次遍历特征向量元素,进行归一化
    {
        ret.push_back(feature[i] / sum); // 将归一化后的值添加到结果向量中
    }
    return ret; // 返回归一化后的特征向量
}


// 提取特征的函数
static void extractFeatures(const std::vector<std::string>& imglist, Net* net, const int& batch_size, const int& resize_h, const int& resize_w, std::vector<std::vector<float>>& features)
{
    for(int st = 0; st < (int)imglist.size(); st += batch_size) // 批量处理图像,每次处理batch_size数量的图像
    {
        std::vector<Mat> batch; // 存储处理后的图像批次的容器
        for(int delta = 0; delta < batch_size && st + delta < (int)imglist.size(); delta++) // 遍历当前批次里的所有图像
        {
            Mat img = imread(imglist[st + delta]); // 读取一张图像
            batch.push_back(preprocess(img)); // 对图像进行预处理,并加入到图像批次中
        }
        Mat blob = dnn::blobFromImages(batch, 1.0, Size(resize_w, resize_h), Scalar(0.0,0.0,0.0), true, false, CV_32F); // 创建一个4维blob作为网络的输入
        net->setInput(blob); // 设置网络的输入数据为blob
        Mat out = net->forward(); // 网络前向传播,输出每一张图像的特征
        for(int i = 0; i < (int)out.size().height; i++) // 遍历每一张图像
        {
            std::vector<float> temp_feature; // 存储单张图像的特征
            for(int j = 0; j < (int)out.size().width; j++) // 遍历提取的特征向量
            {
                temp_feature.push_back(out.at<float>(i,j)); // 读取特征并存储
            }
            features.push_back(normalization(temp_feature)); // 对提取出的特征进行归一化处理,并存储到features中
        }
    }
    return ; // 结束函数,无需返回值
}


static void getNames(const std::string& ImageList, std::vector<std::string>& result)
{
    std::ifstream img_in(ImageList); // 打开图像列表文件
    std::string img_name; // 存储单个图像的名称
    while(img_in >> img_name) // 循环读取图像名称
    {
        result.push_back(img_name); // 将图像名称添加到结果向量中
    }
    return ; // 结束函数
}


static float similarity(const std::vector<float>& feature1, const std::vector<float>& feature2)
{
    float result = 0.0; // 初始化相似度结果为0.0
    for(int i = 0; i < (int)feature1.size(); i++) // 遍历特征向量的每一个维度
    {
        result += feature1[i] * feature2[i]; // 计算两个特征向量的点积,作为相似度度量
    }
    return result; // 返回相似度结果
}
 


// getTopK函数
// 计算查询特征和画廊特征之间的相似性,并获取每个查询特征的前K个最相似画廊特征索引
static void getTopK(const std::vector<std::vector<float>>& queryFeatures, const std::vector<std::vector<float>>& galleryFeatures, const int& topk, std::vector<std::vector<int>>& result)
{
    for(int i = 0; i < (int)queryFeatures.size(); i++)  // 遍历所有查询特征
    {
        std::vector<float> similarityList;  // 存储查询特征与所有画廊特征相似度的列表
        std::vector<int> index;  // 存储画廊特征索引的列表
        for(int j = 0; j < (int)galleryFeatures.size(); j++)  // 遍历所有画廊特征
        {
            similarityList.push_back(similarity(queryFeatures[i], galleryFeatures[j]));  // 计算并存储相似度
            index.push_back(j);  // 存储当前索引
        }
        sort(index.begin(), index.end(), [&](int x,int y){return similarityList[x] > similarityList[y];});  // 根据相似度对索引进行降序排序
        std::vector<int> topk_result;  // 存储前K个索引的列表
        for(int j = 0; j < min(topk, (int)index.size()); j++)  // 选择前K个最相似的特征索引
        {
            topk_result.push_back(index[j]);  // 存储排序后的索引
        }
        result.push_back(topk_result);  // 将结果存入最终结果列表
    }
    return ;
}
// addBorder函数:给图像增加一个固定尺寸的边框
static void addBorder(const Mat& img, const Scalar& color, Mat& result)
{
    const int bordersize = 5;  // 定义边框大小为5
    copyMakeBorder(img, result, bordersize, bordersize, bordersize, bordersize, cv::BORDER_CONSTANT, color);  // 对图像img进行边框扩展,每边增加bordersize个像素宽度,边框类型为固定颜色,颜色由参数color指定
    return ;  // 函数无返回值
}


// drawRankList函数:绘制查询结果的排名列表
static void drawRankList(const std::string& queryName, const std::vector<std::string>& galleryImageNames, const std::vector<int>& topk_index, const int& resize_h, const int& resize_w, Mat& result)
{
    const Size outputSize = Size(resize_w, resize_h);  // 定义输出图像大小
    Mat q_img = imread(queryName), temp_img;  // 读取查询图像queryName,temp_img为临时变量
    resize(q_img, temp_img, outputSize);  // 将查询图像调整到定义的大小
    addBorder(temp_img, Scalar(0,0,0), q_img);  // 给查询图像增加黑色边框
    putText(q_img, "Query", Point(10, 30), FONT_HERSHEY_COMPLEX, 1.0, Scalar(0,255,0), 2);  // 在查询图像上放置文字"Query"
    std::vector<Mat> Images;  // 定义Mat类型的向量,用于存放所有图片
    Images.push_back(q_img);  // 将查询图像加入向量
    for(int i = 0; i < (int)topk_index.size(); i++)  // 遍历topk_index中的所有索引
    {
        Mat g_img = imread(galleryImageNames[topk_index[i]]);  // 读取画廊图像
        resize(g_img, temp_img, outputSize);  // 将读取的画廊图像调整到定义的大小
        addBorder(temp_img, Scalar(255,255,255), g_img);  // 给画廊图像增加白色边框
        putText(g_img, "G" + std::to_string(i), Point(10, 30), FONT_HERSHEY_COMPLEX, 1.0, Scalar(0,255,0), 2);  // 在画廊图像上放置文字(显示排名)
        Images.push_back(g_img);  // 将画廊图像加入向量
    }
    hconcat(Images, result);  // 将所有图像水平拼接成一张图
    return ;  // 函数无返回值
}


// visualization函数:可视化展示查询的排名结果
static void visualization(const std::vector<std::vector<int>>& topk, const std::vector<std::string>& queryImageNames, const std::vector<std::string>& galleryImageNames, const std::string& output_dir, const int& resize_h, const int& resize_w)
{
    for(int i = 0; i < (int)queryImageNames.size(); i++)  // 遍历所有查询图像名称
    {
        Mat img;  // 定义图像变量,用于存放绘制后的排名列表
        drawRankList(queryImageNames[i], galleryImageNames, topk[i], resize_h, resize_w, img);  // 调用drawRankList函数绘制单个查询图像的排名列表
        std::string output_path = output_dir + "/" + queryImageNames[i].substr(queryImageNames[i].rfind("/")+1);  // 定义输出路径,生成每张查询图像的排名图像保存位置
        imwrite(output_path, img);  // 将绘制的排名列表图像写入文件
    }
    return ;  // 函数无返回值
}
};  // 结束命名空间


// main函数
// 程序入口,解析命令行参数,加载网络模型,提取特征,获取相似性排名,并进行结果可视化
int main(int argc, char** argv)
{
    CommandLineParser parser(argc, argv, keys);  // 创建命令行参数解析器


    if (argc == 0 || parser.has("help"))  // 如果没有参数或请求帮助信息
    {
        parser.printMessage();  // 打印帮助信息
        return 0;  // 退出程序
    }
    parser = CommandLineParser(argc, argv, keys);  // 重新创建命令行参数解析器(貌似是多余的)
    parser.about("Use this script to run ReID networks using OpenCV.");  // 关于信息


    // 从命令行参数中获取网络模型路径、查询图像列表、画廊图像列表等信息
    const std::string modelPath = parser.get<String>("model");
    const std::string queryImageList = parser.get<String>("query_list");
    const std::string galleryImageList = parser.get<String>("gallery_list");
    const int backend = parser.get<int>("backend");
    const int target = parser.get<int>("target");
    const int batch_size = parser.get<int>("batch_size");
    const int resize_h = parser.get<int>("resize_h");
    const int resize_w = parser.get<int>("resize_w");
    const int topk = parser.get<int>("topk");
    const std::string output_dir= parser.get<String>("output_dir");


    // 读取图像列表
    std::vector<std::string> queryImageNames;
    reid::getNames(queryImageList, queryImageNames);
    std::vector<std::string> galleryImageNames;
    reid::getNames(galleryImageList, galleryImageNames);


    // 加载网络模型,并设置计算后端和目标设备
    dnn::Net net = dnn::readNet(modelPath);
    net.setPreferableBackend(backend);
    net.setPreferableTarget(target);


    // 提取查询图像特征
    std::vector<std::vector<float>> queryFeatures;
    reid::extractFeatures(queryImageNames, &net, batch_size, resize_h, resize_w, queryFeatures);
    // 提取画廊图像特征
    std::vector<std::vector<float>> galleryFeatures;
    reid::extractFeatures(galleryImageNames, &net, batch_size, resize_h, resize_w, galleryFeatures);


    // 获取查询图像特征和画廊图像特征之间的前K个相似性排名
    std::vector<std::vector<int>> topkResult;
    reid::getTopK(queryFeatures, galleryFeatures, topk, topkResult);
    // 可视化结果
    reid::visualization(topkResult, queryImageNames, galleryImageNames, output_dir, resize_h, resize_w);


    return 0;  // 程序执行完成
}
Mat blob = dnn::blobFromImages(batch, 1.0, Size(resize_w, resize_h), Scalar(0.0,0.0,0.0), true, false, CV_32F);

350850eade5f0433f473113b3a46af47.png

sort(index.begin(), index.end(), [&](int x, int y) {return similarityList[x] > similarityList[y]; });

其利用了C++的STL(Standard Template Library,标准模板库)中的sort函数来对索引进行排序。具体来说,这行代码的作用是根据similarityList中元素的值来对索引进行从大到小的排序

cecdd7fb7031701a003da3a5fdd2a129.png

copyMakeBorder(img, result, bordersize, bordersize, bordersize, bordersize, cv::BORDER_CONSTANT, color);

7dc7a4b9ef062e63f608061aeb3429fe.png

ReID网络的输出:Mat out = net->forward();

b87ec5a49ead7a021be1cde4b4e62a08.png

记录:Debug报错。Release ok

995afcaee2a9c24bdacf4612c23b0d4f.png

C:\Users\cxy\AppData\Local\Programs\Python\Python310\python.exe -m onnxsim youtu_reid_baseline_large.onnx youtu_reid_baseline_large_sim.onnx
C:\Users\cxy\AppData\Local\Programs\Python\Python310\python.exe -m onnxsim youtu_reid_baseline_lite.onnx youtu_reid_baseline_lite_sim.onnx

The End

作者陈晓永:智能装备专业高级职称,软件工程师,机械设计中级职称,机器人与自动化产线仿真动画制作 

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

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

相关文章

华为手机p70即将上市,国内手机市场或迎来新局面?

4月15日&#xff0c;华为官宣手机品牌全新升级&#xff0c;p系列品牌升级为Pura。华为P70系列手机预计将于2024年第一季度末发布&#xff0c;而网友也纷纷表示期待p70在拍照、性能上的全新突破。 网友们对华为P70系列的热情高涨&#xff0c;也印证了国内高端手机市场的潜力巨大…

吴恩达机器学习笔记:第 8 周-13 聚类(Clustering)13.1-13.2

目录 第 8 周 13、 聚类(Clustering)13.1 无监督学习&#xff1a;简介 第 8 周 13、 聚类(Clustering) 13.1 无监督学习&#xff1a;简介 在这个视频中&#xff0c;我将开始介绍聚类算法。这将是一个激动人心的时刻&#xff0c;因为这是我们学习的第一个非监督学习算法。我们…

数仓建模—数据仓库初识

数仓建模—数据仓库初识 数据仓库之父Bill Inmon在1991年出版的"Building the Data Warehouse"一书中所提出的定义被广泛接受 数据仓库&#xff08;Data Warehouse&#xff09;是一个面向主题的&#xff08;Subject Oriented&#xff09;、集成的&#xff08;Integ…

SOLIDWORKS Composer如何使用3D工具实现更真实的动画效果

当我们使用SOLIDWORKS composer创建动画时&#xff0c;往往会涉及到产品的安装与拆解&#xff0c;现实生活中我们在拆卸组装产品的时候&#xff0c;我们往往需要一些工具的协助&#xff0c;比如扳手、螺丝刀等等&#xff0c;那么我们如何在虚拟动画中也将这一过程以逼真的形式展…

【网站项目】新生报到系统小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

【XR806开发板试用】XR806在U8G2上增加MQTT+JSON控制

一、前言 U8G2移植参见之前写的文章 https://aijishu.com/a/1060000000292472本次增加MQTTJSON是站在大佬的肩膀上&#xff0c;参见 https://aijishu.com/a/1060000000284320CJSON的使用&#xff0c;参见 https://blog.csdn.net/fengxinlinux/article/details/53121287 二、成…

Hive进阶(2)----HDFS写入数据流程(赋图助君理解)

HDFS写入数据流程 一、写入流程 1、 Client向NameNode发起RPC请求&#xff0c;来确定请求文件block所在的位置&#xff1b; 2、 NameNode会视情况返回文件的部分或者全部block列表&#xff0c;对于每个block&#xff0c;NameNode都会返回含有该block副本的DataNode地址&…

如何部署npm私有仓库以及在项目中如何使用

如何部署npm私有仓库以及在项目中如何使用 为什么要部署npm私有仓库&#xff1f; 安全性&#xff1a;私有仓库允许团队存放内部研发的、不宜公开发布的代码包&#xff0c;只对特定用户或者团队可见和可用&#xff0c;从而保护公司的知识产权和商业秘密。模块的复用性&#xf…

友元,const成员,static成员变量,static成员函数

友元&#xff1a; friend关键字: 1.友元函数&#xff1a; 语法&#xff1a; friend在类中修饰一个函数。 那么这个函数定义到全局时仍可以访问该类的私有成员的。 (定义时不需要用friend&#xff0c;而是需要在全局定义前&#xff0c;在要使用的成员的类里进行声明&#xff…

备战面试K8S

备战面试&&K8S Kubernetes关于DockerDocker的优缺点分析 WebAssemblyWebAssembly与Container比较 CtrCrictlCtr和CriCtl的区别 Pod生命周期PodConditions容器状态Pod容器组成生命周期的流程 Kubelet EFK日志采集工具的优缺点 Kubernetes 容器运行接口 Container Runti…

Tensorflow小技巧01:检测本地Tensorflow的版本

前言&#xff1a; 以Pycharm为例&#xff0c;Windwos10系统&#xff0c;检测本地环境的Tensorflow的版本&#xff1a; 1 打开Pycharm窗口 2 在窗口中输入&#xff1a; pythonPython 3.9.5 (tags/v3.9.5:0a7dcbd, May 3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win…

ChatGPT与Python-GEE融合,遥感云大数据分析、管理与可视化

掌握Earth Engine的实际应用能力&#xff0c;以Python为基础&#xff0c;结合实例讲解平台搭建、影像数据分析、经典应用案例、本地与云端数据管理&#xff0c;以及云端数据论文出版级可视化等技能。 为提高教学质量&#xff0c;将融入ChatGPT 4、Claude Opus、Gemini、文心一…

Centos7.9 脚本一键部署nextcloud,配置Nginx代理Https。

目录 一键安装nextcloud 出现错误TypeError Cannot read properties of undefined (reading ‘writeText‘) 生成自签名SSL证书 编辑Nginx配置文件 启动Nginx 一键安装nextcloud 本脚本参考文章&#xff0c;本文较长建议先看完在操作&#xff01;&#xff01;&#xff01;…

效率工具:企业微信机器人完成脚本工作-异常监控(sql篇)

效率工具&#xff1a;定时完成脚本工作&#xff08;sql篇&#xff09; 背景&#xff1a;elon在公司需要人工查看某些数据是否异常&#xff0c;并发送到指定企业微信群中。 处理步骤&#xff1a; 工具&#xff1a;企业微信中有机器人 可以指定webhook地址嵌入到脚本中&#xf…

C#语法知识之条件分支语句

4、条件分支语句 目录 4、条件分支语句1、条件分支语句 if1、作用2、if语句3、if...else语句4、if...else if...else语句思考1 只需要0~9数字思考2 语句块 2、条件分支语句 switch1、作用2、基本语法3、default可省略4、自定义常量5、贯穿 1、条件分支语句 if 1、作用 //让顺…

Hive进阶(3)----Checkpoint机制(赋图助君理解)

Checkpoint机制 一、Checkpoint机制概念 本机制可以参考《Hadoop权威指南》第十一章&#xff1a; fsimage文件其实是Hadoop文件系统元数据的一个永久性的检查点&#xff0c;其中包含Hadoop文件系统中的所有目录和文件idnode的序列化信息&#xff1b;fsimage包含Hadoop文件系统…

SpringBoot(一)【入门】

前言 1、SpringBoot 快速入门 1.1、SpringBoot 简介 SpringBoot 是用来简化 Spring 应用的初始搭建以及开发过程 首先我们回顾一下 SpringMVC 项目的开发过程&#xff1a; 导入依赖&#xff08;javax.servlet-api 和 spring-webmvc&#xff09;Servlet 容器配置类&#xff…

Pytest精通指南(14)Parametrize之indirect(间接参数)

文章目录 官方概念概念分析官方示例示例分析验证indirect为True但不指定fixture验证indirect为True但不存在fixture 官方概念 概念分析 在pytest的pytest.mark.parametrize装饰器中&#xff0c;indirect参数用于指示是否应该从fixtures中解析参数值&#xff0c;而不是直接使用提…

爆炸之linux-nacos2.0系列集群安装部署

一、环境配置 1、新建磁盘分区 fdisk /dev/vdb 2、创建文件系统 mkfs.xfs /dev/vdb13、创建挂载点&#xff1a; 在 / 目录下创建一个新的目录作为挂载点。/afc 目录 mkdir /afc4、挂载磁盘&#xff1a; 使用 mount 命令将磁盘挂载到新创建的目录。 mount /dev/vdb /afc5、…

Yoshua Bengio独家专访:我不想把大模型未来押注在Scaling Law上,AGI路上要“注意安全”...

导读 漫长的30年间&#xff0c;数度从主流方向的超然出走&#xff0c;是Bengio的制胜秘诀。这种不盲从主流的风格体现在他研究生涯的方方面面。 90年代末期&#xff0c;神经网络被打入冷宫&#xff0c;Bengio的论文多次遭拒&#xff0c;连学生们也开始担心&#xff0c;和他一起…