segment anything环境配置与使用测试

news2024/12/24 17:23:25

硬件:RTX3070 i9-11900H 内存16G

目录

一、环境配置

二、使用测试--predictor_example.ipynb

1.jupyter notebook准备操作

2.Object masks from prompts with SAM与Environment Set-up

3.Set-up

4.Example image

5.Selecting objects with SAM

6.Specifying a specific object with additional points

7.Specifying a specific object with a box

 8.Combining points and boxes

 9.Batched prompt inputs

10.End-to-end batched inference

三、使用测试--automatic_mask_generator_example.ipynb

1.Environment Set-up

2.Set-up

3.Example image

4.Automatic mask generation

 5.Automatic mask generation options


一、环境配置

首先从官方github上下载并解压在一个目录下,官方github网址:

GitHub - facebookresearch/segment-anythinghttps://github.com/facebookresearch/segment-anything下面进行环境配置:

1.conda创建虚拟环境,注意python版本大于等于3.8(官方要求python>=3.8)。

conda create -n segment python=3.8 -y

2.激活刚刚创建的虚拟环境,安装pytorch,注意官方要求pytorch>=1.7torchvision>=0.8。

conda activate segment
pip install torch==1.10.1+cu113 torchvision==0.11.2+cu113 torchaudio==0.10.1+cu113 -f https://download.pytorch.org/whl/cu113/torch_stable.html

3.本文在pycharm IDE中进行调试,在解压目录下打开pycharm并配置上刚刚配置好的环境,进行后续的环境配置。

pycharm调用conda虚拟环境

进入 pycharm终端terminal进行后续安装

pip install -e .

官方没有给出安装库的详细版本,按照官方给的指令进行执行 

pip install opencv-python pycocotools matplotlib onnxruntime onnx

至此,环境配置完成,后续问题通过程序的报错去补全环境缺失的库或者调整库的版本。

二、使用测试--predictor_example.ipynb

1.jupyter notebook准备操作

官方给的是jupyter notebook的测试流程,首先启动终端进入虚拟环境

conda activate segment

进入官方编写的jupyter notebook的目录下,通过cd的方式,xxx根据实际目录调整

cd xxx:\xxx\segment-anything-main\segment-anything-main\notebooks

注:网上有很多方式去在jupyter notebook调用虚拟环境,我认为最好是在虚拟环境中安装库,如果安装错了可以直接删除虚拟环境,留有容错率且保持conda base环境的简洁,尽量不要在conda base环境中安装多余的库,conda base环境只作为创建虚拟环境的base环境。

在虚拟环境中安装ipykernel,如果不安装,jupyter notebook无法识别到刚刚创建的虚拟环境,即使终端已经启动了虚拟环境。

pip install ipykernel

 将刚刚创建的虚拟环境写入jupyter notebook

模板:

python -m ipykernel install --user --name 虚拟环境名 --display-name "显示名"

实际操作:

python -m ipykernel install --user --name segment --display-name "segment"

 启动jupyter notebook,启动后该终端不要关闭

jupyter notebook

在此图可以发现segment虚拟环境,说明jupyter notebook识别环境配置成功,但是需要配置虚拟环境。

 图中右侧可以看到虚拟环境名。

官方jupyter notebook给的比较详细,首先是predictor_example

接下来按照标题去看官方给的例子

2.Object masks from prompts with SAM与Environment Set-up

关于谷歌colab上运行的操作,由于是本机运行不需要这些操作。

3.Set-up

调用库并定义掩膜、点、矩形框的绘图函数。

4.Example image

为实例图片,通过Opencv读取并展示出来

5.Selecting objects with SAM

为检测测试,分为多个步骤

(1)下载训练好的网络模型,放在项目的model文件夹下,并修改程序中的路径

GitHub - facebookresearch/segment-anything: The repository provides code for running inference with the SegmentAnything Model (SAM), links for downloading the trained model checkpoints, and example notebooks that show how to use the model.https://github.com/facebookresearch/segment-anything#model-checkpoints

 修改路径并添加转义符,模型种类不用修改用的是H大模型。

sam_checkpoint = "D:\\segment-anything-main\\segment-anything-main\\model\\sam_vit_h_4b8939.pth"
model_type = "vit_h"

(2)官方:First, load the SAM model and predictor. Change the path below to point to the SAM checkpoint. Running on CUDA and using the default model are recommended for best results。

翻译:首先,加载 SAM 模型和预测变量。更改下面的路径以指向 SAM 检查点。建议在 CUDA 上运行并使用默认模型以获得最佳结果。

步(1)已经做完了。

(3)官方:Process the image to produce an image embedding by calling SamPredictor.set_imageSamPredictor remembers this embedding and will use it for subsequent mask prediction.

翻译:通过调用 SamPredictor.set_image 处理图像以生成图像嵌入。SamPredictor会记住这个嵌入,并将其用于后续的掩码预测。

在Example image步骤引入的图片,调用了segment_anything/predictor.py中的SamPredictor类中的

set_image函数去接收opencv读取的图像。

(4)官方:To select the truck, choose a point on it. Points are input to the model in (x,y) format and come with labels 1 (foreground point) or 0 (background point). Multiple points can be input; here we use only one. The chosen point will be shown as a star on the image.

翻译:要选择卡车,请选择其上的一个点。点以 (x,y) 格式输入到模型,并带有标签 1(前景点)或 0(背景点)。可以输入多个点;这里我们只使用一个。所选点将在图像上显示为星星。

从这句话可以得知,需要给出一个提示点,提示点用图片坐标系下的坐标,其中左上角为零点,并给出这个点是前景还是背景。程序中给的是:

input_point = np.array([[500, 375]])
input_label = np.array([1])

程序中还将结果展示出来,在原图上加点,绘图的函数在Set-up步骤给出:

plt.imshow(image)
show_points(input_point, input_label, plt.gca())

(5)官方:Predict with SamPredictor.predict. The model returns masks, quality predictions for those masks, and low resolution mask logits that can be passed to the next iteration of prediction.

翻译:使用 SamPredictor.predictor 进行预测。该模型返回掩码、这些掩码的质量预测以及可传递到下一个预测迭代的低分辨率掩码日志。

进入预测部分:

masks, scores, logits = predictor.predict(
    point_coords=input_point,
    point_labels=input_label,
    multimask_output=True,
)

预测的图像已经通过predictor.set_image(image)放入预测器,然后通过predictor.predict()放入提示点与点的标签。

其中multimask_output官方给出解释:With multimask_output=True (the default setting), SAM outputs 3 masks, where scores gives the model's own estimation of the quality of these masks. This setting is intended for ambiguous input prompts, and helps the model disambiguate different objects consistent with the prompt. When False, it will return a single mask. For ambiguous prompts such as a single point, it is recommended to use multimask_output=True even if only a single mask is desired; the best single mask can be chosen by picking the one with the highest score returned in scores. This will often result in a better mask.

翻译:使用 multimask_output=True(默认设置),SAM 输出 3 个掩码,其中分数给出了模型自己对这些掩码质量的估计。 此设置适用于不明确的输入提示,并帮助模型消除与提示一致的不同对象的歧义。 当为 False 时,它将返回一个掩码。 对于单点等不明确的提示,即使只需要一个掩码,也建议使用 multimask_output=True; 最好的单一面具可以通过选择得分最高的面具来选择。 这通常会产生更好的面具。

masks.shape  # (number_of_masks) x H x W
(3, 1200, 1800)

输出的掩码,3个高为1200宽为1800的掩码,为了使用这些掩码,官方给出:

for i, (mask, score) in enumerate(zip(masks, scores)):
    plt.figure(figsize=(10,10))
    plt.imshow(image)
    show_mask(mask, plt.gca())
    show_points(input_point, input_label, plt.gca())
    plt.title(f"Mask {i+1}, Score: {score:.3f}", fontsize=18)
    plt.axis('on')
    plt.show()  

如何实现掩码的显示?参照show_mask()函数中的mask_image = mask.reshape(h, w, 1) * color.reshape(1, 1, -1),具体来说,代码中的reshape函数将mask数组转换为一个形状为(h, w, 1)的三维数组,其中第三维大小为1,表示掩码值。然后,将color数组转换为一个形状为(1, 1, N)的三维数组,其中前两维大小为1,第三维大小为N,表示颜色值。最后,将这两个三维数组进行逐元素相乘,得到一个形状为(h, w, N)的三维数组mask_image,其中第i行第j列的元素表示第i行第j列的像素的颜色值,如果对应的掩码值为N,则该像素的N。这种操作通常用于将掩码应用到图像上,以实现图像的遮罩效果。

 官方原有的结果:

尝试1:通过理解遮罩的显示,我将其进行修改,实现了二值化处理:

通过show_mask修改为show_mask1,展示掩码函数修改颜色,全白透明度改为1

def show_mask1(mask, ax, random_color=False):
    if random_color:
        color = np.concatenate([np.random.random(3), np.array([0.6])], axis=0)
    else:
#         color = np.array([30/255, 144/255, 255/255, 0.6])
        color = np.array([255/255, 255/255, 255/255, 1])
    h, w = mask.shape[-2:]
    mask_image = mask.reshape(h, w, 1) * color.reshape(1, 1, -1)
    ax.imshow(mask_image)

背景设为黑色。

for i, (mask, score) in enumerate(zip(masks, scores)):
    plt.figure(figsize=(10,10))
    image1 = np.zeros((1200, 1800), dtype=np.int8)
    plt.imshow(image1,cmap="gray")
    show_mask1(mask, plt.gca())
    show_points(input_point, input_label, plt.gca())
    plt.title(f"Mask {i+1}, Score: {score:.3f}", fontsize=18)
    plt.axis('on')
    plt.show()  

二值化结果。 

尝试2:根据官方结果改的返回最大分数掩膜:

plt.figure(figsize=(10,10))
plt.imshow(image)
show_mask(masks[np.argmax(scores)], plt.gca())
show_points(input_point, input_label, plt.gca())
plt.title(f"Best Mask Score: {scores[np.argmax(scores)]:.3f}", fontsize=18)
plt.axis('on')
plt.show()  

 

6.Specifying a specific object with additional points

指定具有附加点的特定对象

官方: The single input point is ambiguous, and the model has returned multiple objects consistent with it. To obtain a single object, multiple points can be provided. If available, a mask from a previous iteration can also be supplied to the model to aid in prediction. When specifying a single object with multiple prompts, a single mask can be requested by setting `multimask_output=False`.

翻译:单个输入点不明确,模型返回了与其一致的多个对象。要获得单个对象,可以提供多个点。如果可用,还可以将先前迭代中的掩码提供给模型以帮助预测。指定具有多个提示的单个对象时,可以通过设置“multimask_output=False”来请求单个掩码。

官方给出了两种方式,一种是两点标签全为前景1,一种是一点标签为前景1一点标签为背景0,在此处提示点的标签有了意义。

全为前景1的情况

 一种是一点标签为前景1一点标签为背景0

7.Specifying a specific object with a box

使用框指定特定对象

本文去测试矩形框的表达形式

input_box = np.array([425, 600, 700, 875])

四个值代表着矩形框的左上角与右下角坐标(x,y),调用show_points()函数显示点,直观证明。

plt.figure(figsize=(10, 10))
plt.imshow(image)
show_mask(masks[0], plt.gca())
show_box(input_box, plt.gca())
input_point1 = np.array([[425, 600]])
input_label1 = np.array([1])
input_point2 = np.array([[700, 875]])
input_label2 = np.array([1])
show_points(input_point1, input_label2, plt.gca())
show_points(input_point2, input_label2, plt.gca())
plt.axis('on')
plt.show()

 8.Combining points and boxes

组合点和框

在提示矩形框的基础上加入提示点,官方给汽车的轮毂加入标签为背景0的提示点

input_box = np.array([425, 600, 700, 875])
input_point = np.array([[575, 750]])
input_label = np.array([0])

 我将其修改为前景1,进行测试

input_box = np.array([425, 600, 700, 875])
input_point = np.array([[575, 750]])
input_label = np.array([1])

 9.Batched prompt inputs

批处理提示输入

官方:SamPredictor can take multiple input prompts for the same image, using predict_torch method. This method assumes input points are already torch tensors and have already been transformed to the input frame. For example, imagine we have several box outputs from an object detector.

翻译:SamPredictor可以使用predict_torch方法为同一图像获取多个输入提示。此方法假定输入点已经是tensor张量,并且已经转换为输入帧。例如,假设我们有几个来自对象检测器的盒子输出。

input_boxes = torch.tensor([
    [75, 275, 1725, 850],
    [425, 600, 700, 875],
    [1375, 550, 1650, 800],
    [1240, 675, 1400, 750],
], device=predictor.device)

官方:Transform the boxes to the input frame, then predict masks. SamPredictor stores the necessary transform as the transform field for easy access, though it can also be instantiated directly for use in e.g. a dataloader (see segment_anything.utils.transforms).

翻译:将框转换为输入帧,然后预测遮罩。SamPredictor将必要的转换存储为转换字段,以便于访问,尽管它也可以直接实例化以用于例如数据加载器(请参阅segment_anything.utils.transforms)。

多个矩形框需要先进行转换

transformed_boxes = predictor.transform.apply_boxes_torch(input_boxes, image.shape[:2])

使用for循环,显示所有的掩膜和矩形框

for mask in masks:
    show_mask(mask.cpu().numpy(), plt.gca(), random_color=True)
for box in input_boxes:
    show_box(box.cpu().numpy(), plt.gca())

 我尝试将上一步的提示点加入其中

transformed_boxes = predictor.transform.apply_boxes_torch(input_boxes, image.shape[:2])
masks, _, _ = predictor.predict_torch(
    point_coords=input_point,
    point_labels=input_label,
    boxes=transformed_boxes,
    multimask_output=False,
)

出现报错,不允许这么做。

10.End-to-end batched inference

端到端批量推理

官方:If all prompts are available in advance, it is possible to run SAM directly in an end-to-end fashion. This also allows batching over images.

翻译:如果所有提示都提前可用,则可以以端到端的方式直接运行 SAM。这也允许对图像进行批处理。

本文测试此部分直接爆显存了,8G显存都不够!简单的应用不需要批量处理。尽量使用单张图片进行处理。

三、使用测试--automatic_mask_generator_example.ipynb

Automatically generating object masks with SAM使用 SAM 自动生成对象遮罩

官方:

Since SAM can efficiently process prompts, masks for the entire image can be generated by sampling a large number of prompts over an image. This method was used to generate the dataset SA-1B.

The class SamAutomaticMaskGenerator implements this capability. It works by sampling single-point input prompts in a grid over the image, from each of which SAM can predict multiple masks. Then, masks are filtered for quality and deduplicated using non-maximal suppression. Additional options allow for further improvement of mask quality and quantity, such as running prediction on multiple crops of the image or postprocessing masks to remove small disconnected regions and holes.

翻译:

由于 SAM 可以有效地处理提示,因此可以通过对图像上的大量提示进行采样来生成整个图像的掩码。 该方法用于生成数据集 SA-1B。 SamAutomaticMaskGenerator 类实现了此功能。 它通过在图像上方的网格中对单点输入提示进行采样来工作,SAM 可以从每个提示中预测多个掩码。 然后,使用非最大抑制对掩码进行质量过滤和重复数据删除。 其他选项允许进一步改进蒙版质量和数量,例如对图像的多个裁剪运行预测或后处理蒙版以删除小的不连接区域和孔洞。

从翻译可知生成数据集 SA-1B用的这个方法,达到大量生成数据集功能,在论文中也有说明。

还是通过标题的形式去测试

1.Environment Set-up

这是在谷歌colab上的操作,本文本机测试不需要这一步。

2.Set-up

导入了一些必要的库,同时给出绘制多个掩膜的函数,不同于之前的Set-up,之前是绘制点、绘制矩形和绘制单个掩膜函数,从此处得知与之前功能是不同的。

def show_anns(anns):
    if len(anns) == 0:
        return
    sorted_anns = sorted(anns, key=(lambda x: x['area']), reverse=True)
    ax = plt.gca()
    ax.set_autoscale_on(False)

    img = np.ones((sorted_anns[0]['segmentation'].shape[0], sorted_anns[0]['segmentation'].shape[1], 4))
    img[:,:,3] = 0
    for ann in sorted_anns:
        m = ann['segmentation']
        color_mask = np.concatenate([np.random.random(3), [0.35]])
        img[m] = color_mask
    ax.imshow(img)

3.Example image

导入图片,与之前相同,通过opencv去导入

4.Automatic mask generation

自动生成掩膜,此掩膜为一个字典,其中包含如下键

['segmentation', 'area', 'bbox', 'predicted_iou', 'point_coords', 'stability_score', 'crop_box']
  • segmentation : the mask
  • area : the area of the mask in pixels
  • bbox : the boundary box of the mask in XYWH format
  • predicted_iou : the model's own prediction for the quality of the mask
  • point_coords : the sampled input point that generated this mask
  • stability_score : an additional measure of mask quality
  • crop_box : the crop of the image used to generate this mask in XYWH format

把之前画矩形框和点的函数导入进来,绘制出预测矩形框

 5.Automatic mask generation options

自动掩模生成选项

官方:There are several tunable parameters in automatic mask generation that control how densely points are sampled and what the thresholds are for removing low quality or duplicate masks. Additionally, generation can be automatically run on crops of the image to get improved performance on smaller objects, and post-processing can remove stray pixels and holes. Here is an example configuration that samples more masks:

翻译:自动掩码生成中有几个可调参数,用于控制采样点的密度以及去除低质量或重复掩码的阈值。 此外,生成可以在图像的裁剪上自动运行以提高较小对象的性能,并且后处理可以去除杂散像素和孔洞。 以下是对更多掩码进行采样的示例配置:

说明自动掩膜生成可以调参。

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

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

相关文章

GeoServer安装部署

GeoServer是一款开源的GIS服务器,用于管理、共享和编辑空间数据。 它的主要功能包括: 管理空间数据:GeoServer可以连接各种空间数据源,包括文件(SHP、CSV等)、数据库(PostGIS,Oracle,SQL Server等)和云存储(S3,Swift,Azure等)。并提供数据的浏览、上传、下载和删除…

webgpu之旅04

继续继续 319854902 319854902 319854902 319854902 webgpu交Q流群首先准备好绘制到屏幕所需的这个descriptor if rendertarget this._textures.initRenderTarget( renderTarget ); 来看一下这个函数里面会做什么 renderTargetProperties是这个target的properties 创建一个co…

历时一个月,腾讯认证python全套项目实战笔记,终于整理出来了

前言 之前拿到一份关于腾讯认证的python的全套项目实战脑图,于是历时花费一个月,终于是熬夜加点的给肝出来了,先用typora全部写出来,然后再导出成PDF文件,目前已经完全搞定。 总共划分内容为(七大模块&am…

Telnet协议详解

Telnet协议是一种远程登录协议,它允许用户通过网络连接到远程主机并在远程主机上执行命令。本文将对Telnet协议进行详细介绍,包括其基本概念、连接方式、C/S模式以及工作原理。 一、Telnet协议的基本概念 1. NVT(Network Virtual Terminal&a…

通付盾荣获第六届(2023)数字金融创新大赛“创新先锋榜”!

今日,第六届(2023)数字金融创新大赛“创新先锋榜”揭晓,大赛由中国电子银行网、数字金融联合宣传年主办,自4月6日开启以来,得到数字金融行业各方的积极响应与支持。经过专家评分、路演评审等环节&#xff0…

Android中Activity、View和Window关系详解

Android系统启动篇 1,《android系统启动流程简介》 2,《android init进程启动流程》 3,《android zygote进程启动流程》 4,《Android SystemServer进程启动流程》 5,《android launcher启动流程》 6,…

8年测试总结,App测试要点常见bug分类,从功能到性能测试...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 而针对手机应用软…

数字IC设计怎么入门?(附学习全流程)

看到很多小伙伴都不了解数字IC设计该怎么学,下面就来给大家来具体讲讲。 其实对于初级数字 IC 设计工程师而言,不仅仅需要较好的 Verilog 语法功底,还要熟悉企业的 Linux 环境以及 EDA 工具,此时你就需要掌握 Shell,V…

Django 权限管理和guardian插件

内置权限管理 Django内置的权限管理, 是一种表权限, 就是可分别配置某管理员用户对某个表的全部数据有没有增删改查4种权限. 图形界面配置权限 之前提到,使用命令行创建超管用户: python manage.py createsuperuser这其实是在最普通的用户的基础上将…

百度网盘的最新插件(懂得都懂)

下面先给大家介绍一下油猴插件。 这个插件为什么叫油猴? 现在我们经常提到的油猴插件,常指Tampermonkey,但Tampermonkey翻译过来是叫篡改猴,为什么会叫油猴呢?原因是因为另一个插件Greasemonkey,它翻译过…

Qt编写iFIx组态软件日报表插件的实现

一、iFIx中生成report.MDB文件 在Ifxi组态软件的【调度】中新建调度任务【report】添加【定时器调度项】FixTimer5,间隔1h触发一次。通过此任务及脚本程序,将相关变量定时存入自动生成的report.MDB文件中。 用户脚本程序如下: ---- User Co…

Sui对外开放开发者Office Hour

Sui宣布开启新一轮的Sui开发工程师Office Hour。本期的Office Hour由Sui基金会和Mysten Labs共同主办,为Sui上开发的相关技术问题进行答疑解惑并提供支持。 开发工程Office Hour将于每周五1:00 AM(GMT8)开设,时长为1小时。 每个…

程序性能优化实践总结——JAVA

文章目录 1、 衡量程序性能的指标2、Java 程序性能优化切入点3、获取程序的性能数据1、nmon:获取系统性能数据2、jvisualvm:获取JVM性能数据3、jmc:获取Java应用详细性能数据4、arthas:获取单个请求的调用链耗时5、wrk获取Web接口的性能数据 4、应用程序优化1、缓冲区2、缓存3、…

vm.min_free_kbytes调整导致GI异常,kernel: oracle: page allocation failure

有个11204 rac的测试环境,客户反馈凌晨rman全备时偶尔会有内存耗尽导致数据库重启的情况,不是合同内的维护环境,请我们帮忙处理。我估计是没配置vm.min_free_kbytes,之前也调整多次每次都成功完成,就没有多想&#xff…

ROS1 图像数据转发

为节约带宽提高效率采用jpeg: sensor_msgs::CompressedImage image_msg; ros::Publisher img_pub n.advertise<sensor_msgs::CompressedImage>(“image1”, 10); image_msg.format“jpeg” ; image_msg.data.resize(jpeg_data_size); memcpy(image_msg.data.data(),jpeg…

【CUDA编程】 动态体素化实现

动态体素化实现 动态体素化DV克服了硬体素化HV的一些缺点。动态体素化DV保留了分组grouping阶段&#xff0c;相反&#xff0c;它没有采样固定的点数或体素容量&#xff0c;它保留了点和体素之间的完全映射。因此&#xff0c;体素数和每个体素中的点数都是动态的&#xff0c;依…

深入理解 SpringBoot 日志框架:从入门到高级应用——(七)SpringBoot日志配置

SpringBoot 官方文档&#xff1a;https://docs.spring.io/spring-boot/docs/2.7.12/reference/htmlsingle SpringBoot 底层依赖 Spring Boot 对所有内部日志记录使用 Commons Logging&#xff0c;但使底层日志实现保持为打开状态。 为 Java Util Logging、Log4J2 和 Logback …

【计算机网络自顶向下】如何学好计网-第一章概论

相关术语 URI&#xff1a;Uniform Resource Identifier 统一资源标识符&#xff0c;指的是一个资源 URL&#xff1a;Uniform Resource Location 统一资源定位符&#xff0c;URI的子集&#xff0c;用地址定为的方式指定一个资源 URN&#xff1a;Uniform Resource Name 统一资…

DBeaver连接SQLite数据库

一、前言 SQLite小巧轻便的开源免费关系型数据库&#xff0c;适合嵌入单机应用随身携带。桌面版推荐使用DBeaver。 官网&#xff1a;SQLite Download Page github&#xff1a;GitHub - sqlite/sqlite: Official Git mirror of the SQLite source tree 类似的开源免费且小巧…

vue+elementui实现app布局小米商城,样式美观大方

目录 一、效果图 1.首页效果图 2.分类 3.购物车 4.我的 5.登录注册 6.商品详情 7.搜索 二、项目实现 1.项目结构、设计说明 2.路由配置实现 3.首页实现源码 4.登录注册实现&#xff0c;模拟登录注册流程&#xff0c;用户数据存储到本地浏览器缓存 三、总结 一、效果…