当前位置: 首页 > news >正文

基于Tensorflow+SDD+Python人脸口罩识别系统(深度学习)含全部工程源码及模型+视频演示+图片数据集

目录

  • 前言
  • 总体设计
    • 系统整体结构图
    • 系统流程图
  • 运行环境
    • Python 环境
    • Anaconda 环境搭建
  • 模块实现
    • 1. 数据预处理
    • 2. 模型构建及算法实现
    • 3. 模型生成
  • 系统测试
    • 1. 训练准确率
    • 2. 运行结果
  • 工程源代码下载
  • 其它资料下载

在这里插入图片描述

前言

在当今全球范围内,新冠疫情对我们的生活方式带来了巨大的改变。在公共场所,佩戴口罩成为了常态,以保护我们自己和他人的健康安全。然而,这也给人脸识别技术带来了新的挑战。如何准确地辨别佩戴口罩的人成为了一个重要的问题。

本文介绍的一种基于Tensorflow、SDD和Python的人脸口罩识别系统,结合了深度学习技术和计算机视觉算法,能够高效地检测人脸并准确地判断是否佩戴口罩。通过使用这个系统,我们可以更好地管理公共场所的出入口,确保员工、顾客和访客的健康安全。

当然,您可以在文末下载本系统的全部工程源码(包括Web demo)进行个人二次开发。

总体设计

本部分包括系统整体结构图和系统流程图。

系统整体结构图

系统整体结构如图所示。

在这里插入图片描述

系统流程图

系统流程如图所示。

在这里插入图片描述

运行环境

本部分包括 Python 环境和Anaconda 环境。

Python 环境

需要 Python 3.5 及以上配置,在 Windows 环境下推荐下载 Anaconda 完成 Python 所需的配置,下载地址:https://www.anaconda.com/,也可以下载虚拟机在 Linux 环境下运行代码。

Anaconda 环境搭建

打开 Anaconda Prompt,输入清华仓库镜像。

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config –set show_channel_urls yes

创建 Python3.5 的环境,名称为 TensorFlow:

conda create -n tensorflow python=3.5

有需要确认的地方,都输入 y。
在 Anaconda Prompt 中激活 TensorFlow 环境:

activate tensorflow

安装 CPU 版本的 TensorFlow:

pip install –upgrade --ignore-installed tensorflow

安装完毕。

模块实现

本项目包括 3 个模块:数据预处理、模型构建及算法实现、模型生成,下面分别给出各模块的功能介绍及相关代码。

1. 数据预处理

WIDER Face 和 MAFA 这两个数据集包含了大量的人脸及人脸佩戴口罩的图片,但只使用WIDER Face 数据集,所含其他遮挡脸部的图片较少(如用手挡住脸部),会出现识别偏差的情况。因此,从 WIDER Face 数据集中选取 3894 张图片、MAFA 数据集中选取 4064张图片,包含戴口罩、不戴口罩、用其他物体遮挡面部共 8000 张图片进行训练。
数据集下载链接:https://pan.baidu.com/s/1nsQf_Py5YyKm87-8HiyJeQ 提取码:eyfz

2. 模型构建及算法实现

数据加载进模型之后,需要定义模型结构,并进行算法实现。

1. 定义模型结构

定义的架构共 28 个卷积层,其中有 8 个主干层,即特征提取层;20 个定位和分类层。每个卷积层的通道数是 32、64、128 三种,为了能够更好地运行在终端设备上,模型设计的较小,共 101.5 万个参数,输入为 260*260 大小的图片。

2. 算法实现
基于 SSD 检测模型推理,实现以下三步:生成全部的 anchor、网络输出值根据全部的anchors 解码、NMS(非极大值抑制)即可,即以下三个函数:

function anchorGenerator()function decodeBBox()function nonMaxSuppression()

训练目标检测模型,最重要的是合理设置 anchor 的大小和宽高比。所谓 anchor 是指在图像上预设好的不同大小,不同长宽比的参照框。假设一个 256*256 大小的图片,经过 64、128 和 256 倍下采样,会产生 4X4、2X2、1X1 大小的特征图,每个点上都设置三个不同大小的 anchor。在实际的 SSD 模型中,300X300 的输入下,anchor 数量也特别多,在38X38、19X19、10X10、5X5、3X3、1X1 的六个特征图上,每个点分别设置 4、6、6、6、6、4 个不同大小和长宽比的 anchor,一共有 38X38X4+ 19X19X6+ 10X10X6+ 5X5X6+3X3X4+ 1X1X4= 8732个 anchor。借助卷积神经网络,可直接输出每个 anchor 是否包含(与物体有较大重叠,也就是 IoU 较大)物体,以及被检测物体相对本 anchor 的中心点偏移、长宽比例。

在训练的时候,也就是给每张图片物体的 Bounding Box,相对于 anchor 进行编码,如果物体 Bounding Box 与某个 anchor 的 IoU 较大,例如,大于 0.5 认为是正样本,否则是负样本。

对于检测网络,有的实现,是用没有归一化的坐标,例如,anchor 设置为(30, 42)尺度大小,但是,有的算法实现,是将坐标和物体框的宽高比,除以图片的宽和高。如果图片都是正方形的,那归一化后宽高比没有变化,如果是 1080P 分辨率的摄像头,那么长宽比是16:9。本来就小的宽度,再除以 1920,而高度除以 1080,会导致归一化后的人脸高度是宽度的 2 倍左右。归一化处理即:

BBOX_NORMALIZE = True

根据数据的分布,将五个定位层的 anchor 的宽高比统一设置为 1,0.62, 0.42。(转换为高宽比,也就是约 1,1.6:1,2.4:1)。

3. 代码实现

# -*- coding:utf-8 -*-
import cv2
import time
import argparseimport numpy as np
from PIL import Image
from keras.models import model_from_json
from utils.anchor_generator import generate_anchors
from utils.anchor_decode import decode_bbox
from utils.nms import single_class_non_max_suppression
from load_model.tensorflow_loader import load_tf_model, tf_inference# 载入模型
sess, graph = load_tf_model('models/face_mask_detection.pb')
# anchor configuration
#特征图大小
feature_map_sizes = [[33, 33], [17, 17], [9, 9], [5, 5], [3, 3]]
#anchor大小
anchor_sizes = [[0.04, 0.056], [0.08, 0.11], [0.16, 0.22], [0.32, 0.45], [0.64, 0.72]]
#anchor宽高比
anchor_ratios = [[1, 0.62, 0.42]] * 5# generate anchors
anchors = generate_anchors(feature_map_sizes, anchor_sizes, anchor_ratios)# 用于推断,批大小为 1,模型输出形状为 [1,N,4],因此将锚点的 dim 扩展为 [1,anchor_num,4]
anchors_exp = np.expand_dims(anchors, axis=0)id2class = {0: 'Mask', 1: 'NoMask'}# 用训练好的模型做预测
def inference(image,conf_thresh=0.5,iou_thresh=0.4,target_shape=(160, 160),draw_result=True,show_result=True):'''  检测推理的主要功能# :param image:3D numpy 图片数组#  :param conf_thresh:分类概率的最小阈值。#  :param iou_thresh:网管的 IOU 门限#  :param target_shape:模型输入大小。#  :param draw_result:是否将边框拖入图像。#  :param show_result:是否显示图像。'''output_info = []height, width, _ = image.shape#获取初始图像的长宽image_resized = cv2.resize(image, target_shape)#改变图像尺寸image_np = image_resized / 255.0  # 归一化到0~1image_exp = np.expand_dims(image_np, axis=0) #扩展图片维度y_bboxes_output, y_cls_output = tf_inference(sess, graph, image_exp)#构建图,返回包含预测结果的框和颜色# 删除批次维度,因为用于推断批次始终是1。y_bboxes = decode_bbox(anchors_exp, y_bboxes_output)[0]y_cls = y_cls_output[0]# 为了加快速度,执行单类 NMS,而不是多类 NMS。即戴口罩人脸和不戴口罩人脸两个类别一起做NMSbbox_max_scores = np.max(y_cls, axis=1)bbox_max_score_classes = np.argmax(y_cls, axis=1)# keep_idx 是 nms 之后的活动边界框。keep_idxs = single_class_non_max_suppression(y_bboxes,bbox_max_scores,conf_thresh=conf_thresh,iou_thresh=iou_thresh,)for idx in keep_idxs:conf = float(bbox_max_scores[idx])class_id = bbox_max_score_classes[idx]bbox = y_bboxes[idx]# 裁剪坐标,避免该值超出图像边界。xmin = max(0, int(bbox[0] * width))ymin = max(0, int(bbox[1] * height))xmax = min(int(bbox[2] * width), width)ymax = min(int(bbox[3] * height), height)

3. 模型生成

该应用主要有两部分,一是对图片中的人脸进行识别;二是对视频中出现的人脸进行识别。

1. 调用训练好的模型

sess, graph = load_tf_model('models\face_mask_detection.pb') #载入模型

2. 图片处理

1)anchor 设定完成后,进行识别
2)解码及非极大值抑制

		if draw_result:if class_id == 0:color = (0, 255, 0)#戴口罩显示绿框else:color = (255, 0, 0) #没戴口罩显示红框cv2.rectangle(image, (xmin, ymin), (xmax, ymax), color, 2)#图像,左上角坐标,右下角坐标 ,颜色,粗细cv2.putText(image, "%s: %.2f" % (id2class[class_id], conf), (xmin + 2, ymin - 2),cv2.FONT_HERSHEY_SIMPLEX, 0.8, color)#图片,添加的文字,左上角坐标,字体,字体大小,颜色output_info.append([class_id, conf, xmin, ymin, xmax, ymax])if show_result:Image.fromarray(image).show()return output_info

3. 视频处理

#视频检测
def run_on_video(video_path, output_video_name, conf_thresh):cap = cv2.VideoCapture(video_path) #读取本地视频height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)#计算视频的高width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)#计算视频的宽fps = cap.get(cv2.CAP_PROP_FPS)#得到视频的帧率fourcc = cv2.VideoWriter_fourcc(*'XVID')#XVID是MPEG-4编码类型,文件名后缀为.avi# writer = cv2.VideoWriter(output_video_name, fourcc, int(fps), (int(width), int(height)))total_frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)#获取视频总帧数if not cap.isOpened():#视频打开失败raise ValueError("Video open failed.")returnstatus = Trueidx = 0while status:start_stamp = time.time()#返回当前时间的时间戳status, img_raw = cap.read()#第一个参数ret 为True 或者False,代表有没有读取到图片# #第二个参数frame表示截取到一帧的图片img_raw = cv2.cvtColor(img_raw, cv2.COLOR_BGR2RGB)#色彩空间BGR转为RGBread_frame_stamp = time.time()if (status):inference(img_raw,conf_thresh,iou_thresh=0.5,target_shape=(260, 260),draw_result=True,show_result=False)#调用推断cv2.imshow('image', img_raw[:, :, ::-1])cv2.waitKey(1)inference_stamp = time.time()# writer.write(img_raw)write_frame_stamp = time.time()idx += 1#循环直到识别到口罩,然后输出帧数和时间.print("%d of %d" % (idx, total_frames))print("read_frame:%f, infer time:%f, write time:%f" % (read_frame_stamp - start_stamp,inference_stamp - read_frame_stamp,write_frame_stamp - inference_stamp))# writer.release()

系统测试

本部分包括模型训练准确率及模型测试效果。

1. 训练准确率

戴口罩的人脸识别准确率接近 92%,可识别绝大部分戴口罩的人脸,如图所示。

在这里插入图片描述

2. 运行结果

1. 在命令行中运行

# 跟命令行有关的
if __name__ == "__main__":# 跟命令行有关的parser = argparse.ArgumentParser(description="Face Mask Detection") # 创建解析器parser.add_argument('--img-mode', type=int, default=1, help='set 1 to run on image, 0 to run on video.')#这里设置为 1:检测图片;还是设置为 0:视频文件(实时图像数据)检测parser.add_argument('--img-path', type=str, help='path to your image.')parser.add_argument('--video-path', type=str, default='0', help='path to your video, `0` means to use camera.')# parser.add_argument('--hdf5', type=str, help='keras hdf5 file')args = parser.parse_args()# 把parser中设置的所有"add_argument"给返回到args子类实例当中, 那么parser中增加的属性内容都会在args实例中,使用即可。if args.img_mode:imgPath = args.img_path#图片路径img = cv2.imread(imgPath)#读取图片img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)#转换色彩空间(R,G,B换个位置)inference(img, show_result=True, target_shape=(260, 260))else:video_path = args.video_path#视频路径if args.video_path == '0':video_path = 0run_on_video(video_path, '', conf_thresh=0.5)

运行方法如下:

  • 如果您要运行图片,需要:
python tensorflow_infer.py --img-path /path/to/your/img

如果您要在视频上运行,需要:

python tensorflow_infer.py --img-mode 0 --video-path /path/to/video 

如果要打开本地摄像头, video_path 填写 0 就可以:

python tensorflow_infer.py --img-mode 0 --video-path 0

2. 运行结果

照片测试结果如图所示:

在这里插入图片描述

工程源代码下载

详见本人博客资源下载页

其它资料下载

如果大家想继续了解人工智能相关学习路线和知识体系,欢迎大家翻阅我的另外一篇博客《重磅 | 完备的人工智能AI 学习——基础知识学习路线,所有资料免关注免套路直接网盘下载》
这篇博客参考了Github知名开源平台,AI技术平台以及相关领域专家:Datawhale,ApacheCN,AI有道和黄海广博士等约有近100G相关资料,希望能帮助到所有小伙伴们。

相关文章:

基于Tensorflow+SDD+Python人脸口罩识别系统(深度学习)含全部工程源码及模型+视频演示+图片数据集

目录 前言总体设计系统整体结构图系统流程图 运行环境Python 环境Anaconda 环境搭建 模块实现1. 数据预处理2. 模型构建及算法实现3. 模型生成 系统测试1. 训练准确率2. 运行结果 工程源代码下载其它资料下载 前言 在当今全球范围内,新冠疫情对我们的生活方式带来了…...

abc200 D 鸽巢原理

题意:https://www.luogu.com.cn/problem/AT_abc200_d 思路:对于一个序列最多有多少个模数,其实就是子序列个数,所以当子序列个数超过200是那么答案一定存在,那么我们就可以直接枚举了,所以我们直接枚举前八…...

QT day1 (图形界面设计)

要求&#xff1a; 功能函数模块 #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow) {qDebug("%s","hello world");//qDebug() << &qu…...

JS逆向系列之猿人学爬虫第9题-动态cookie2

文章目录 目标参数流程分析js代码Python调用测试目标 https://match.yuanrenxue.cn/match/9参数流程分析 二次请求cookie携带m 第一次请求响应内容格式化之后是这样的: < body > < script src = "/static/match/safety/match9/udc.js" > <...

Java ~ Reference ~ FinalizerHistogram【总结】

前言 文章 相关系列&#xff1a;《Java ~ Reference【目录】》&#xff08;持续更新&#xff09;相关系列&#xff1a;《Java ~ Reference ~ FinalizerHistogram【源码】》&#xff08;学习过程/多有漏误/仅作参考/不再更新&#xff09;相关系列&#xff1a;《Java ~ Referenc…...

【MySQL】一文带你了解SQL

&#x1f3ac; 博客主页&#xff1a;博主链接 &#x1f3a5; 本文由 M malloc 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;LeetCode刷题集&#xff01; &#x1f3c5; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指…...

python基础学习3【NumPy矩阵与通用函数【矩阵相乘+平方+广播机制+转置】+ save、load、sort、repeat、unique、鸢尾花1】

NumPy矩阵与通用函数 a np.mat([[1,2],[3,4]])#生成矩阵b np.matrix([[1,7],[6,4]])np.bmat("a b") 矩阵的运算 矩阵特有属性&#xff1a; 属性 说明 T自身转置H共轭转置I逆矩阵A自身数据的二维数据视图 例如&#xff1a; np.matrix(a).T 矩阵相乘&#xff1a;…...

【Spring学习之更简单的读取和存储Bean对象】教会你使用五大类注解和方法注解去存储 Bean 对象

前言&#xff1a; &#x1f49e;&#x1f49e;今天我们依然是学习Spring&#xff0c;这里我们会更加了解Spring的知识&#xff0c;知道Spring是怎么更加简单的读取和存储Bean对象的。也会让大家对Spring更加了解。 &#x1f49f;&#x1f49f;前路漫漫&#xff0c;希望大家坚持…...

微客云原生淘宝客APP小程序系统如何定制

淘宝是中国最大的电商网站&#xff0c;而淘宝的火热&#xff0c;也兴起了一个全新的行业&#xff0c;淘宝客。就是帮助淘宝商家推广商品的一种职业。目前淘宝每年有百分之10的销售业绩都是通过淘宝客贡献的&#xff0c;所以说淘宝客的市场越来越大。但是淘宝客要推广自己的产品…...

QT CTK插件开发(六) 多对一插件

CTK在软件的开发过程中可以很好的降低复杂性、使用 CTK Plugin Framework 提供统一的框架来进行开发增加了复用性 将同一功能打包可以提供多个应用程序使用避免重复性工作、可以进行版本控制提供了良好的版本更新迭代需求、并且支持动态热拔插 动态更新、开发更加简单快捷 方便…...

【Spring Boot整合MyBatis教程】

Spring Boot是由Pivotal团队提供的全新框架&#xff0c;其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置&#xff0c;从而使开发人员不再需要定义样板化的配置。通过这种方式&#xff0c;Spring Boot致力于在蓬勃发展的快速应用开发…...

ThinkPHP3.2.3通过局域网手机访问项目

折腾一上午&#xff0c; 试了nginx&#xff0c; 试了修改Apache的httpd.conf 试了关闭代理 试了手动配置网络 试了关闭防火墙 试了添加防火墙入站出站规则 问了五个ChatGPT 都没解决。 记录一下 wampserver3.0.4 Apache2.4.18 PHP 5.6.19 MySQL 5.7.11 所有服务启…...

2306C++虚继承

构 B{无序映<串,串>列;整 大小0;空 f(){大小;} }; //虚继承其实不错,但是占位置,占空间.构 C:虚 公 B{空 g(){} };构 D:虚 公 C{空 h(){} }; 构 S{}; 构 T{}; //元<类 T>构 E:虚 公 D{}; 构 E:虚 公 D{};空 主(){//E<S>e;e.f();打印(e.大小);//E<T>m;m…...

使用oracle遇到问题笔记

一、oracle还原到不同版本的oracle数据库报错和解决办法 产生&#xff1a;执行imp导入dmp备份文件时报错 错误内容&#xff1a;导入失败提示&#xff1a;“不是有效的导出文件, 标头验证失败”解决方法 解决办法&#xff1a;http://t.csdn.cn/pJyhc...

我和老刘又被搞惨了

前两天在调试PHY的时候遇到了一堆问题&#xff0c;老刘都不耐其烦的搞定了&#xff0c;这次我们开始调试音频部分&#xff0c;音频部分很简单&#xff0c;无非就是录音&#xff0c;要是能把录音的音频拿到了&#xff0c;那就万事大吉了。老刘也是信心满满&#xff0c;老刘对我说…...

DDD--基本概念

最近项目组一直在推DDD领域驱动设计&#xff0c;现就一些个人理解分享如下。 DDD&#xff08;领域驱动设计&#xff09;是一种软件开发方法论&#xff0c;旨在解决复杂业务场景下的软件设计与开发问题。以下是DDD的基本概念&#xff1a; 领域&#xff08;Domain&#xff09;&…...

chatgpt赋能python:Python多行注释

Python 多行注释 在 Python 中&#xff0c;我们经常需要写注释来解释代码或者用于调试。Python 的注释分为单行注释和多行注释&#xff0c;本文主要介绍 Python 中如何多行注释。 单行注释 在 Python 中&#xff0c;单行注释以符号 # 开头&#xff0c;可以写在代码的任何位置…...

JSP详细基础教学

目录 前言 环境设置 创建JSP文件 编写基本的JSP代码 部署和运行JSP页面 基础语法 前言 JSP&#xff08;JavaServer Pages&#xff09;是一种用于开发动态网页的Java技术。它允许将Java代码嵌入HTML页面中&#xff0c;以便在服务器端生成动态内容。在本次教程中&#xff…...

mysql修改登录用户的密码

文章目录 mysql5.7即mysql7.0 的修改方式mysql5.8即mysql8.0的修改方式如果修改完密码&#xff0c;发现旧密码和新密码都登录不进来怎么办&#xff1f;发现设置密码老报错 mysql5.7即mysql7.0 的修改方式 1.如果是使用docker里装的mysql 首先使用 [rootlocalhost /]# docker p…...

SNAT和DNAT

SNAT和DNAT 一、SNAT的策略及应用&#xff1a; 1.SNAT&#xff1a; &#xff08;1&#xff09;定义&#xff1a;又称源地址转换。源地址转换是内网地址向外访问时&#xff0c;发起访问的内网ip地址转换为指定的ip地址&#xff08;可指定具体的服务以及相应的端口或端口范围&…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...