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

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); // 设置网络的输入数据为blobMat 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.0for(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;  // 定义边框大小为5copyMakeBorder(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.mzph.cn/bicheng/265.shtml

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

相关文章

OpenHarmony网络通信-socket-io

简介 socket.io是一个在客户端和服务器之间实现低延迟、双向和基于事件的通信的库。建立在 WebSocket 协议之上&#xff0c;并提供额外的保证&#xff0c;例如回退到 HTTP 长轮询或自动重新连接。 效果展示 下载安装 ohpm install ohos/socketio OpenHarmony ohpm 环境配置等更…

VulnHub靶机 DC-5 打靶 渗透测试详情过程

VulnHub靶机 DC-5 打靶 详细渗透测试过程 目录 VulnHub靶机 DC-5 打靶 详细渗透测试过程一、将靶机导入到虚拟机当中二、渗透流程主机发现端口扫描目录爆破文件包含getshell反弹shell提权 一、将靶机导入到虚拟机当中 靶机地址&#xff1a; https://download.vulnhub.com/dc/…

【云计算】云计算八股与云开发核心技术(虚拟化、分布式、容器化)

【云计算】云计算八股与云开发核心技术&#xff08;虚拟化、分布式、容器化&#xff09; 文章目录 一、什么是云计算&#xff1f;1、云计算的架构&#xff08;基础设施&#xff0c;平台&#xff0c;软件&#xff09;2、云计算的发展 二、如何做云计算开发&#xff1f;云计算的核…

量子时代加密安全与区块链应用的未来

量子时代加密安全与区块链应用的未来 现代密码学仍然是一门相对年轻的学科&#xff0c;但其历史却显示了一种重要的模式。大多数的发展都是基于几年甚至几十年前的研究。而这种缓慢的发展速度也是有原因的&#xff0c;就像药物和疫苗在进入市场之前需要经过多年的严格测试一样&…

心学从0开始学习rust-十万个为什么篇章(持续更新篇章)

问答环节 1.const x 1;和let x 1有何区别呢&#xff0c;const申请的是全局变量所以会一直有效对吗&#xff1f; const 声明的常量具有全局作用域&#xff0c;但它们不能直接在函数内部声明。常量通常用于定义整个程序中使用的值&#xff0c;如配置常量或数学常量。 let 声明…

tcp网络编程——2

1.一个服务器只能有一个客户端连接&#xff08;下面代码&#xff09; ​​​​​​​tcp网络编程&#xff08;基础&#xff09;-CSDN博客 2.一个服务器可以有多个客户端连接&#xff08;多线程&#xff09; server端创建多个线程&#xff0c;每个线程与不同的client端建立连…

浅写个登录(无js文件)

全部代码如下&#xff0c;无需编写wxss文件&#xff0c;渲染都在style里面&#xff1a; <view style"height: 250rpx;width: 100%;"> <!-- 背景图片 --><view style"position: absolute; background-color: antiquewhite; height: 250rpx;width…

IDEA中Docker相关操作的使用教程

一、引言 Docker作为当前最流行的容器化技术&#xff0c;极大地简化了应用的部署和管理。而IntelliJ IDEA作为一款强大的集成开发环境&#xff0c;也提供了对Docker的集成支持。本文将介绍如何在IDEA中配置和使用Docker&#xff0c;包括远程访问配置、服务连接、Dockerfile编写…

【C语言】冒泡排序算法详解

目录 一、算法原理二、算法分析时间复杂度空间复杂度稳定性 三、C语言实现四、Python实现 冒泡排序&#xff08;Bubble Sort&#xff09;是一种基础的排序算法。它重复地遍历要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果他们的顺序错误就把他们交换过来。遍历数列…

微信小程序开发笔记

微信小程序开发笔记 1 微信小程序的项目结构 2 页面组成 一个微信小程序是由一个或多个页面组成的&#xff0c;这些页面被存放在pages目录中。下面以pages 目录下的index页面为例展示其组成部分&#xff0c;index页面的组成部分如下图所示。 由上图可知&#xff0c;index页面…

hbase-2.2.7分布式搭建

一、下载上传解压 1.在官网或者云镜像网站下载jar包 华为云镜像站&#xff1a;Index of apache-local/hbase/2.2.7 2.上传到linux并解压 tar -zxvf hbase-2.2.7-bin.tar.gz -C /usr/locol/soft 二、配置环境变量 1. vim /etc/profile export HBASE_HOME/usr/local/soft/h…

前端三剑客 HTML+CSS+JavaScript ② HTML相关概念

他们这样形容我 是暴雨浇不灭的火 —— 24.4.18 学习目标 理解 HTML的概念 HTML的分类 HTML的关系 HTML的语义化 应用 HTML骨架格式 sublime基本使用 一、HTML初识 HTML指的是超文本标记语言&#xff0c;是用来描述网页的一种语言 超文本&#xff1a;暂且理解为“超级的文本”&…

【opencv】dnn示例-segmentation.cpp 通过深度学习模型对图像进行实时语义分割

模型下载地址&#xff1a; http://dl.caffe.berkeleyvision.org/ 配置文件下载&#xff1a; https://github.com/opencv/opencv_extra/tree/4.x/testdata/dnn 该段代码是一个利用深度学习进行语义分割的OpenCV应用实例。下面将详细解释代码的功能和方法。 引入库 引入了一些必要…

(最详细)关于List和Set的区别与应用

关于List与Set的区别 List和Set都继承自Collection接口&#xff1b; List接口的实现类有三个&#xff1a;LinkedList、ArrayList、Vector。Set接口的实现类有两个&#xff1a;HashSet(底层由HashMap实现)、LinkedHashSet。 在List中&#xff0c;List.add()是基于数组的形式来添…

内部类

一.概念 当一个事物内部&#xff0c;还有一个部分需要一个完整的结构进行描述&#xff0c;而这个内部的完整的结构又只为外部事物提供服务&#xff0c;那么将这个内部的完整结构最好使用内部类。在Java中&#xff0c;可以将一个类定义在另一个类或者一个方法内部&#xff0c;前…

将gdip-yolo集成到yolov9模型项目中(支持预训练的yolov9模型)

1、yolov9模型概述 1.1 yolov9 YOLOv9意味着实时目标检测的重大进步&#xff0c;引入了可编程梯度信息&#xff08;PGI&#xff09;和通用高效层聚合网络&#xff08;GELAN&#xff09;等开创性技术。该模型在效率、准确性和适应性方面取得了显著改进&#xff0c;在MS COCO数…

GNU Radio使用Python Block实现模块运行时间间隔获取

文章目录 前言一、timestamp_sender 模块二、timestamp_receiver 模块三、测试 前言 GNU Radio 中没有实现测量两个模块之间的时间测量模块&#xff0c;本文记录一下通过 python block 制作一个很简单的测时 block。 一、timestamp_sender 模块 使用 python block 做一个发送…

【python】super()函数的用法详解!

今天分享一个我在实际项目中用到过的super()函数&#xff0c;来说说该函数的主要功能是什么&#xff0c;简单来说&#xff0c;super()函数是用来做调用父类的一个方法。 super() 是用来解决多重继承问题的&#xff0c;直接用类名调用父类方法在使用单继承的时候没问题&#xf…

外包干了30天,技术倒退明显

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落&#xff01; 而我已经在一个企业干了四年的功能…

【详细的Kylin使用心得】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…