人脸识别打卡系统--基于QT(附源码)
逃离舒适区
项目源代码放在我的仓库中,有需要自取
项目地址
https://gitcode.com/hujiahangdewa/Face_recognition.git
文章目录
- 一、项目结构分析
- 二、服务器的搭建
- 三、客户端的搭建
- 四、人脸识别库的申请
- 五、基于人脸识别库的识别判断
- 六、QT人脸识别----调用百度ai接口
- 七、如何在Qt中添加图片素材
- 八、项目总结
本项目需要准备到的工具:qt6.8.0、VMware17、Ubuntu24.10、百度AI人脸识别库的密钥、摄像头(笔记本电脑自带即可)
一、项目结构分析
- 本项目选用Linux系统来搭建服务器,首先我们要明白一点就是在Linux系统中一切
皆文件 - 我们的客户端使用QT来搭建
- 本项目中的客户端与服务器之间的通信采用TCP/IP协议
- 人脸识别算法采用了百度AI中的人脸识别库(免费)
二、服务器的搭建
- 首先先检查我们的虚拟机的USB功能有没有启用
windows+R调出这个窗口,输入以下命令
找到VMware USB Arbitration Service,将其启动
启动虚拟机,将摄像头连入虚拟机)
检查摄像头是否连接成功:唤起命令行,输入cheese即可检查 - 结构分析
总的来说就是服务器端打开摄像头,将摄像头拍摄的数据传输到客户端中显示出来。
接下来我们来看看关于摄像头的头文件的结构
#ifndef CAMERA_H
#define CAMERA_H#include <stddef.h> // for size_t#define BUFFER_COUNT 4struct camera
{void *start;size_t length;
};struct buffer_info
{int index;char *pic_buf;int length;
};extern struct camera buffer[BUFFER_COUNT];
extern struct v4l2_buffer buf;
extern struct buffer_info buf_info;/*** @brief 初始化摄像头** @param pathname 摄像头设备的路径。* @return 成功时返回文件描述符,失败时返回 -1。*/
int camera_init(const char *pathname);/*** @brief 启动摄像头采集** @param fd 摄像头设备的文件描述符。* @return 成功时返回 0,失败时返回 -1。*/
int camera_start(int fd);/*** @brief 获取一帧数据** @param fd 摄像头设备的文件描述符。* @param pic_buf 指向图像数据的指针。* @param length 图像数据的长度。* @return 成功时返回 0,失败时返回 -1。*/
int camera_get(int fd, char **pic_buf, int *length);/*** @brief 将已处理的缓冲区重新放入缓存队列** @param fd 摄像头设备的文件描述符。* @return 成功时返回 0,失败时返回 -1。*/
int camera_input(int fd);/*** @brief 停止摄像头流** @param fd 摄像头设备的文件描述符。*/
void camera_stop(int fd);#endif // CAMERA_H
- 服务器的具体实现(代码)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "camera.h"int main(int argc, char *argv[])
{// 创建socket套接字int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("socket");return -1;}printf("create socket success!\n");// 设置地址信息struct sockaddr_in addr;addr.sin_family = AF_INET; // 地址协议族IPv4addr.sin_port = htons(65432); // 端口号addr.sin_addr.s_addr = inet_addr("0.0.0.0"); // IP地址socklen_t addrlen = sizeof(addr);// bind绑定地址信息 端口号int bind_info = bind(sockfd, (const struct sockaddr *)&addr, addrlen);if (bind_info < 0){perror("bind");return -1;}printf("bind socket success!\n");// listen监听if (listen(sockfd, 5) < 0){perror("listen");return -1;}printf("listen socket success!\n");// 摄像头的初始化int camera_fd = camera_init("/dev/video0");if (camera_fd < 0){printf("camera init failed\n");return -1;}printf("camera_init success\n");// 服务器搭建完毕,保证服务器不停while (1){struct sockaddr_in c_addr;socklen_t c_addrlen = sizeof(c_addr);int conn_fd = accept(sockfd, (struct sockaddr *)&c_addr, &c_addrlen);if (conn_fd < 0){perror("accept");continue;}printf("client connect success! conn_fd:%d\n", conn_fd);// 开启摄像头----------->摄像头开始获取数据if (camera_start(camera_fd) < 0){printf("camera start failed\n");return -1;}// 连接成功,保证服务程序持续运行while (1){// 服务程序--->发送视频信息// 采集(获取)一帧图像char *pic_buf = NULL; // 定义存放图像数据的指针int length = 0; // 定义保存图像大小的变量if (camera_get(camera_fd, &pic_buf, &length) < 0){printf("camera get failed\n");continue;}// 1.先发送图像的大小char len[8] = {0};sprintf(len, "%d", length);write(conn_fd, len, 8);// 2.发送图像的数据write(conn_fd, pic_buf, length);// 清除存放图像的缓冲区if (camera_input(camera_fd) < 0){printf("camera_input close failed\n");continue;}}}// 摄像头停止工作camera_stop(camera_fd);// 关闭文件描述符close(camera_fd);// 关闭通信的套接字close(sockfd);return 0;
}
以上服务器代码中的第55行中,由于设备的不同,我们需要进行更换,如果以上代码出现摄像头无法显示的问题,将/dev/video0修改为dev/video1,即可解决。
接下来编译这个服务器文件,使用gcc来编译
gcc server.c -o app -L ./ -lcamera
其中lcamera是摄像头的一些驱动库
- 启动服务器
这即是服务器启动成功之后的界面,如若启动失败,在评论区留下错误原因。
三、客户端的搭建
- 创建项目
打开我们的QT软件,创建一个qt项目,具体如何创建可参考这个文章https://blog.csdn.net/hujiahangdewa/article/details/143915238?spm=1001.2014.3001.5501
我们需要在项目文件的.pro文件中添加以下模块,这里面含有tcp/ip协议的构造函数
QT += network
2.设计ui界面
点击左侧的widget.ui即可进入到ui界面的设计
从左侧的控件栏中拖出三个按钮(Push Button),根据需要可以进行更名如下:
那我们用什么来显示摄像头传输给我们的图像数据呢?---------使用label或者TextEdit
这里我们就使用label来显示我们的图像数据
我们还需要两个文本框来输入我们服务器的IP地址和端口号
在控件栏中拖出两个LineEdit即可,如下
ui界面的简单布局就是这样,美化的事情可以后期再做。
接下来我们要理解一个很重要的一个QT的核心理念就是----信号与槽
当我们点击登录按钮就是一个鼠标的点击事件。
- 按钮槽函数的设计
(1)登录按钮的槽函数
我们先选中登录按钮,右键,转到槽,在弹出的提示框中选择clicked()
void Widget::on_pushButton_clicked()
{QString IP=ui->lineEdit->text(); //获取IP地址int PORT=ui->lineEdit_2->text().toInt(); //获取端口号client->connectToHost(IP,PORT);//连接到服务器,前提是服务器是启动状态
}
接下来就是当我们登录成功之后,在label框中实时显示我们摄像头拍摄的数据
我们来到widget.cpp这个文件中,新建一个recv函数
void Widget::recv()
{static int flag=0;//第一次读取图像的大小//第二次读取图像的数据if(flag==0){//判断数据是否有效if(client->bytesAvailable()<8){return;}length = client->read(8).toInt();flag=1;}else if(flag==1){//判断数据是否有效if(client->bytesAvailable()<length)//说明图片没有传完{return;}pic = client->read(length);QPixmap pix;//定义一个图片类型变量pix.loadFromData(pic);//显示图像ui->label_3->setPixmap(pix);ui->label_3->setScaledContents(true);flag=0;}
}
然后我们需要在Widget的构造函数中进行信号和槽的绑定
//实例化客户端对象,通信协议client=new QTcpSocket;
//接收信号与接收槽函数的绑定//信号对象 信号 槽函数对象 对象connect(client, &QTcpSocket::readyRead, this, &Widget::recv);
同时启动服务器和客户端,在客户端输入服务器的IP和端口号,登陆成功之后,我们的label框中会显示摄像头拍摄到的数据。如下
(2)注册人脸信息按钮的槽函数
//人脸信息的注册
void Widget::on_pushButton_3_clicked()
{QPixmap pix;//定义一个图片类型变量pix.loadFromData(pic);//显示图像ui->label_4->setPixmap(pix);ui->label_4->setScaledContents(true);//上传的人脸信息QImage image;image.loadFromData(pic);//获取用户的组QString group_id = ui->lineEdit_3->text();//获取用户的IDQString user_id = ui->lineEdit_4->text();//进行人脸信息的注册AI->insert_user(image,group_id,user_id);}
(3)打卡按钮的槽函数
//打卡的槽函数
void Widget::on_pushButton_2_clicked()
{QPixmap pix;//定义一个图片类型变量pix.loadFromData(pic);//显示图像ui->label_4->setPixmap(pix);ui->label_4->setScaledContents(true);//上传的人脸信息QImage image;image.loadFromData(pic);//获取用户的组QString group_id = ui->lineEdit_3->text();//进行人脸检测AI->search_face(image,group_id);}
//绑定信号与槽//1.绑定识别成功的信号与槽connect(AI, &face::recv_nub, this, &Widget::face_success);
//人脸识别成功的槽函数
void Widget::face_success(QString user_id,double number)
{QString data = "打卡成功,欢迎" + user_id +"业主回家!"+" "+"相似度为:"+QString::number(number);ui->textEdit->setText(data);}
四、人脸识别库的申请
接下来我们将教大家如何申请
首先进入到百度AI的控制台
https://console.bce.baidu.com/#/index/overview
在这个界面中,在人工智能的那一列找到人脸识别,点击应用列表,点击创建应用,根据提示完成创建。然后在返回到应用列表界面,
这里的API KEY和Secret Key很重要,是我们调用百度ai的密钥
返回到我们的qt软件
来到widget.cpp,在widget的构造函数中初始化百度ai,以及输入密钥
//实例化一个百度ai对象AI = new face("API_KEY","SECRET_KEY"); //API_KEY SECRET_KEY
五、基于人脸识别库的识别判断
- 识别失败
- 识别成功
//绑定信号与槽//1.绑定识别成功的信号与槽connect(AI, &face::recv_nub, this, &Widget::face_success);//2.绑定识别失败的信号与槽connect(AI, &face::recv_dis, this, &Widget::face_failure); //连接人脸识别失败信号到新的槽函数connect(AI, &face::recv_error_msg, this, &Widget::showErrorMsg); // 连接接收错误信息信号到显示错误信息的槽函数
//人脸识别成功的槽函数
void Widget::face_success(QString user_id,double number)
{QString data = "打卡成功,欢迎" + user_id +"业主回家!"+" "+"相似度为:"+QString::number(number);ui->textEdit->setText(data);
}
void Widget::face_failure()
{QMessageBox::warning(this, "打卡失败", "人脸识别未通过,请重新尝试打卡。");
}
//显示错误信息的槽函数,弹出提示框显示具体错误消息
void Widget::showErrorMsg(QString errorMsg)
{QMessageBox::critical(this, "错误", "发生错误:" + errorMsg);
}
六、QT人脸识别----调用百度ai接口
我们注册的人脸信息将会保存在百度AI的人脸库中,每隔一个月会消除一次。
以下代码就是调用这个接口的具体实现
#ifndef FACE_H
#define FACE_H#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QImage>
#include <QBuffer>
#include <QDebug>
#include <QPixmap>class face : public QObject
{Q_OBJECT
public:explicit face(QObject *parent = nullptr);//构造face类,需要传递api_key值和secret_keyface(QString,QString);/********************************************************************************************** 进行人脸库搜索* 参数说明:* 1.图像内容为Qimage类型* 2.查询的用户组*********************************************************************************************/void search_face(QImage,QString);/********************************************************************************************** 添加用户信息,即实现用户人脸注册,当用户存在时添加用户图片,用户不存在添加用户和图片* 参数说明:* 1.图像内容为Qimage类型* 2.添加的用户组* 3.添加到的用户名id*********************************************************************************************/void insert_user(QImage,QString,QString);/********************************************************************************************** 添加用户组* 参数说明:* 添加的用户*********************************************************************************************/void insert_group(QString);/**********************************************************************************************获取access_token值* api_key和secret_key来自于构造该对象时传的参数*********************************************************************************************/void get_access_token();signals:/********************************************************************************************** 该对象的信号,触发该信号返回人脸搜索的用户名id和对比度得分* 触发条件,人脸对比与用户信息阈值超过80则触发*********************************************************************************************/void recv_nub(QString,double);/********************************************************************************************** 触发条件,人脸对比与用户信息阈值低于80则触发*********************************************************************************************/void recv_dis();//用于返回错误码的信号,该信号触发返回错误信息void recv_error_msg(QString);public slots://接收由networkaccessmanager发起的网络请求的网络返回数据,并解析void recv_json(QNetworkReply*);private:QNetworkAccessManager *my_access_manager;QString api_key;QString secret_key;QString access_token;QString user_id;double score;
};#endif // FACE_H
#include "face.h"face::face(QObject *parent) : QObject(parent)
{}face::face(QString ak,QString sk)
{api_key = ak;secret_key = sk;//实例化网络请求管理工具my_access_manager = new QNetworkAccessManager;//关联信号与槽connect(my_access_manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(recv_json(QNetworkReply*)));get_access_token();}
//获取access_token值,发起网络请求
void face::get_access_token()
{QNetworkRequest req;req.setUrl(QUrl(QString("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%0&client_secret=%1").arg(api_key).arg(secret_key)));req.setHeader(QNetworkRequest::ContentTypeHeader,"Content-Type:application/json");QByteArray buf;my_access_manager->post(req,buf);
}
//发起人脸检测的网络请求
void face::search_face(QImage image,QString group_id)
{//将接收到的image类型转化为qpixmap类QPixmap pic = QPixmap::fromImage(image);//存储图像数据到字节数组内QByteArray buf;QBuffer b(&buf);b.open(QIODevice::ReadWrite);pic.save(&b,"jpg");b.close();//封装百度api请求需要的json格式类型数据QJsonObject obj;//图像数据格式要求base64格式obj.insert("image",QString(buf.toBase64()));obj.insert("image_type","BASE64");obj.insert("group_id_list",group_id);//实例化网络请求QNetworkRequest req;//表明网络请求发起的请求地址req.setUrl(QUrl(QString("https://aip.baidubce.com/rest/2.0/face/v3/search?access_token=%0").arg(access_token)));//设置网络请求头req.setHeader(QNetworkRequest::ContentTypeHeader,"Content-Type:application/json");//发起post网络请求my_access_manager->post(req,QJsonDocument(obj).toJson());
}
//发起添加用户的网络请求
void face::insert_user(QImage image,QString group_id,QString user_id)
{QPixmap pic = QPixmap::fromImage(image);QByteArray buf;QBuffer b(&buf);b.open(QIODevice::ReadWrite);pic.save(&b,"jpg");b.close();//封装数据内添加需要增加到的用户组,用户id以及该用户的图像数据QJsonObject obj;obj.insert("image",QString(buf.toBase64()));obj.insert("image_type","BASE64");obj.insert("group_id",group_id);obj.insert("user_id",user_id);obj.insert("action_type","APPEND");QNetworkRequest req;req.setUrl(QUrl(QString("https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add?access_token=%0").arg(access_token)));req.setHeader(QNetworkRequest::ContentTypeHeader,"Content-Type:application/json");my_access_manager->post(req,QJsonDocument(obj).toJson());
}
//发起添加用户组的网络请求
void face::insert_group(QString group_id)
{//封装组idQJsonObject obj;obj.insert("group_id",group_id);QNetworkRequest req;req.setUrl(QUrl(QString("https://aip.baidubce.com/rest/2.0/face/v3/faceset/group/add?access_token=%0").arg(access_token)));req.setHeader(QNetworkRequest::ContentTypeHeader,"Content-Type:application/json");my_access_manager->post(req,QJsonDocument(obj).toJson());
}
//解析接收到的网络请求的返回数据
void face::recv_json(QNetworkReply *rep)
{//读取网络请求后的返回数据QByteArray replay = rep->readAll();//将数据转化为json文档QJsonDocument doc = QJsonDocument::fromJson(replay);if(doc.isObject()){//将json文档转化为json对象QJsonObject replay_obj = doc.object();//判定json数据内所包含的字样,并获取字样对应的数据值if(replay_obj.contains("result")){QJsonValue val = replay_obj.value("result");if(val.isObject()){QJsonObject replay_obj = val.toObject();if(replay_obj.contains("user_list")){QJsonValue val = replay_obj.value("user_list");if(val.isArray()){QJsonArray arr = val.toArray();QJsonValue val = arr.at(0);if(val.isObject()){QJsonObject replay_obj = val.toObject();if(replay_obj.contains("user_id"))//解析用户id{user_id = replay_obj.value("user_id").toString();}if(replay_obj.contains("score"))//解析人脸比对的阈值{score = replay_obj.value("score").toDouble();if(score > 80)//比对得分超过80认为是同一个人,可以触发信号返回用户id和对比值{qDebug()<<score;emit this->recv_nub(user_id,score);}else{emit this->recv_dis();}}}}}}}//解析access_token值if(replay_obj.contains("access_token")){access_token = replay_obj.value("access_token").toString();}//解析错误码if(replay_obj.contains("error_msg")){QString error_msg = replay_obj.value("error_msg").toString();if(error_msg!="SUCCESS"){//触发信号返回错误信息emit this->recv_error_msg(error_msg);}}//解析access_token值的错误码else if(replay_obj.contains("error_description")){QString error_description = replay_obj.value("error_description").toString();emit this->recv_error_msg(error_description);}}
}
完成以上之后,我们的项目基本完成,剩下的就是美化工作,我们可以根据自己的喜好来进行美化。
七、如何在Qt中添加图片素材
在这个界面中选择Qt,然后选择Qt Resource File
取一个名字,存放位置建议默认,也可根据情况而修改,接下来的设置默认就可。
完成以上步骤之后,会出现这样一个界面,点击添加前缀
建议是设置成以下这样
然后点击添加文件,我们就可以自由的添加图片文件了。我们的文件列表中会出现一个.prc的资源文件
八、项目总结
相关文章:

人脸识别打卡系统--基于QT(附源码)
逃离舒适区 项目源代码放在我的仓库中,有需要自取 项目地址 https://gitcode.com/hujiahangdewa/Face_recognition.git 文章目录 一、项目结构分析二、服务器的搭建三、客户端的搭建四、人脸识别库的申请五、基于人脸识别库的识别判断六、QT人脸识别----调用百度ai…...
【深度学习入门】深度学习知识点总结
一、卷积 (1)什么是卷积 定义:特征图的局部与卷积核做内积的操作。 作用:① 广泛应用于图像处理领域。卷积操作可以提取图片中的特征,低层的卷积层提取局部特征,如:边缘、线条、角。 ② 高层…...

通过视觉语言模型蒸馏进行 3D 形状零件分割
大家读完觉得有帮助记得关注和点赞!!!对应英文要求比较高,特此说明! Abstract This paper proposes a cross-modal distillation framework, PartDistill, which transfers 2D knowledge from vision-language models …...

机器学习10-解读CNN代码Pytorch版
机器学习10-解读CNN代码Pytorch版 我个人是Java程序员,关于Python代码的使用过程中的相关代码事项,在此进行记录 文章目录 机器学习10-解读CNN代码Pytorch版1-核心逻辑脉络2-参考网址3-解读CNN代码Pytorch版本1-MNIST数据集读取2-CNN网络的定义1-无注释版…...

微服务学习-Gateway 统一微服务入口
1. 微服务为什么需要 API 网关? 1.1. 在微服务架构中,通常一个系统会被拆分为多个微服务,面对多个微服务客户端应该如何去调用呢? 如果根据每个微服务的地址发起调用,存在如下问题: 客户端多次请求不同的…...

2025寒假备战蓝桥杯02---朴素二分查找升级版本的学习+分别求解左右端点
文章目录 1.朴素二分查找的升级版2.查找左端点3.查找右端点4.代码的编写 1.朴素二分查找的升级版 和之前介绍的这个二分查找相比,我觉得这个区别就是我们的这个二分查找需要找到的是一个区间,而不是这个区间里面的某一个元素的位置; 2.查找…...
PHP语言的软件工程
PHP语言的软件工程 引言 软件工程是计算机科学中的一个重要分支,它涉及软件的规划、开发、测试和维护。在现代开发中,PHP作为一种流行的服务器端脚本语言,广泛应用于网页开发和各种企业应用中。本文将深入探讨PHP语言在软件工程中的应用&am…...

linux-FTP服务配置与应用
也许你对FTP不陌生,但是你是否了解FTP到底是个什么玩意? FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为 “文传协议” 用于Internet上的控制文件的双向传输。同时,它也是一个应用程序…...

靠右行驶数学建模分析(2014MCM美赛A题)
笔记 题目 要求分析: 比较规则的性能,分为light和heavy两种情况,性能指的是 a.流量与安全 b. 速度限制等分析左侧驾驶分析智能系统 论文 参考论文 两类规则分析 靠右行驶(第一条)2. 无限制(去掉了第一条…...

(1)STM32 USB设备开发-基础知识
开篇感谢: 【经验分享】STM32 USB相关知识扫盲 - STM32团队 ST意法半导体中文论坛 单片机学习记录_桃成蹊2.0的博客-CSDN博客 USB_不吃鱼的猫丿的博客-CSDN博客 1、USB鼠标_哔哩哔哩_bilibili usb_冰糖葫的博客-CSDN博客 USB_lqonlylove的博客-CSDN博客 USB …...

Spring中如何动态的创建、监听MQ以及创建Exchange
文章目录 前言动态创建和管理Exchange、Queue动态消费Queue结论 前言 前面我们学习 RabbitMQ 的时候,都是在编译的时候就确定了Exchange、Queue,也就是说我们需要在程序启动之前就创建好需要的Exchange和Queue,但是实际使用的时候࿰…...

中国综合算力指数(2024年)报告汇总PDF洞察(附原数据表)
原文链接: https://tecdat.cn/?p39061 在全球算力因数字化技术发展而竞争加剧,我国积极推进算力发展并将综合算力作为数字经济核心驱动力的背景下,该报告对我国综合算力进行研究。 中国算力大会发布的《中国综合算力指数(2024年…...

【Python项目】小区监控图像拼接系统
【Python项目】小区监控图像拼接系统 技术简介:采用Python技术、B/S框架、MYSQL数据库等实现。 系统简介:小区监控拼接系统,就是为了能够让业主或者安保人员能够在同一时间将不同地方的图像进行拼接。这样一来,可以很大程度的方便…...

常用排序算法之插入排序
目录 前言 一、基本原理 1.算法步骤 2.动画演示 3.插入排序的实现代码 二、插入排序的时间复杂度 1. 时间复杂度 1.最优时间复杂度 2.最差时间复杂度 3.平均时间复杂度 2. 空间复杂度 三、插入排序的优缺点 1.优点 2.缺点 四、插入排序的改进与变种 五、插入排…...
Elasticsearch(ES)基础查询语法的使用
1. Match Query (全文检索查询) 用于执行全文检索,适合搜索文本字段。 { “query”: { “match”: { “field”: “value” } } } match_phrase:精确匹配短语,适合用于短语搜索。 { “query”: { “match_phrase”: { “field”: “text” }…...

一篇文章学会Milvus【Docker 中运行 Milvus(Windows),Python实现对Milvus的操作,源代码案例,已经解决巨坑】【程序员猫爪】
一篇文章学会Milvus【Docker 中运行 Milvus(Windows),Python实现对Milvus的操作,源代码案例,已经解决巨坑】【程序员猫爪】 一、Milvus 是什么?【程序员猫爪】1、Milvus 是一种高性能、高扩展性的向量数据库…...

前端之移动端
视口 布局视口 layout viewport 视口(viewport)就是浏览器显示页面内容的屏幕区域。 视口可以分为布局视口、视觉视口和理想视口 一般移动设备的浏览器都默认设置了一个布局视口,用于解决早期的PC端页面在手机上显示的问题。 iOS, Androi…...

记一次 SpringBoot 启动慢的问题
记一次 SpringBoot 启动慢的问题 背景问题描述分析处理Flame Graph 火焰图Call Tree 调用树关键词检索尝试解决 为什么这样反向检索问题梳理 复盘处理流程为什么 Reference 背景 最近临时接了一个任务,就从一个旧 springboot 项目 copy 出来,临时写个服…...

高效安全文件传输新选择!群晖NAS如何实现无公网IP下的SFTP远程连接
文章目录 前言1. 开启群晖SFTP连接2. 群晖安装Cpolar工具3. 创建SFTP公网地址4. 群晖SFTP远程连接5. 固定SFTP公网地址6. SFTP固定地址连接 前言 随着远程办公和数据共享成为新常态,如何高效且安全地管理和传输文件成为了许多人的痛点。如果你正在寻找一个解决方案…...
如何在Python中进行JSON数据的序列化和反序列化?
在Python中,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。Python内置的json模块提供了简单易用的方法来实现数据的序列化和反序列化。下面将详细介绍如何…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
全面解析数据库:从基础概念到前沿应用
在数字化时代,数据已成为企业和社会发展的核心资产,而数据库作为存储、管理和处理数据的关键工具,在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理,到社交网络的用户数据存储,再到金融行业的交易记录处理&a…...

如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...