Python项目实战:基于napari的3D可视化(点云+slice)

文章目录

  • 一、napari 简介
  • 二、napari 安装与更新
  • 三、napari【巨巨巨大的一个BUG】
  • 四、napari 使用指南
    • 4.1、菜单栏(File + View + Plugins + Window + Help)
    • 4.2、Window:layer list(参数详解)
    • 4.3、Window:layer controls(points layer + shapes layer + labels layer)
  • 五、项目实战
    • 5.1、查看图像:napari.view_image()
    • 5.2、添加图像:viewer.add_image()
    • 5.3、添加点云:viewer.add_points()
    • 5.4、添加形状:viewer.add_shapes() —— 获取线条坐标(起点和终点)
  • 六、在napari中自定义组件,并与PyQt完成交互

一、napari 简介

基于 Python 编写的快速、交互式多维图像查看器

🥗napari 官网首页:https://napari.org/0.4.18/index.html#
🥪napari 使用案例:https://napari.org/0.4.18/gallery.html#gallery

二、napari 安装与更新

  • 安装napari:pip install napari
  • 更新napari:pip install --upgrade napari

三、napari【巨巨巨大的一个BUG】

  • 【BUG】:点击View - Toggle Full Screen将最大化软件界面,且菜单栏和很多按钮都将不可用。
  • 【影响】:此时,想要任何操作都无法退出最大化,即使关闭后重试,卸载后重试都无法达到,没有试过关机后重试。
  • 【解决方法】:Window + Tab切换窗口,菜单栏可以短暂有效且可点击,瞬间点击View - Toggle Full Screen,可解除BUG。

四、napari 使用指南

4.1、菜单栏(File + View + Plugins + Window + Help)

File(文件)
1Open File打开文件
2Opencv File as Stack打开文件(适用于大尺度)
3Open Sample + napari builtins(提供了很多的内置样本)初学者可以直接导入后研究
4Preferences设置(主题 + 快捷键等等)
5Save Selected Layer(s)(所有帧图像)保存选定的单层或多层(指定后缀,修改图像格式)
6Save All Layers(所有帧图像)保存所有层(指定后缀,修改图像格式)
7Save Screenshot(单帧图像)保存当前窗口内容(不显示界面)
8Save Screenshot with Viewer(单帧图像)保存整个视图内容(图像 + 界面)
  • Plugins(插件):安装和卸载插件(也可以自定义)
View(视图)
1Axes
2Scale Bar刻度条
3Toggle Full Screen切换全屏
4Toggle Menubar Visibity切换菜单可见性
5Toggle Paly切换面板
6Toggle Layer Tooltips切换图层工具提示
7Toggle Activity Dock切换活动区
Window(窗口)
1console控制面板(命令行窗口)
2layer controls图层控制(点层、形状层、标签层)
3layer list图层列表
Help(帮助)直接跳转官网页面
1Getting started开始
2Tutorials教程
3Using Layers Guides使用图层指南
4Examples Gallery示例图库
5Release Notes版本说明
6napari homepagenapari 主页
7napari Infonapari 信息

4.2、Window:layer list(参数详解)

在这里插入图片描述

4.3、Window:layer controls(points layer + shapes layer + labels layer)

在这里插入图片描述

五、项目实战

5.1、查看图像:napari.view_image()

在napari查看器中显示单个或多个图像,并提供了许多可选参数来自定义图像的显示。

在这里插入图片描述

import napari
import tifffileimage_path = 'output_8bit.tif'
marked_image = tifffile.imread(image_path)viewer = napari.view_image(marked_image, name='image', rgb=False)
napari.run()
# 备注:若不添加napari.run(),将避免程序阻塞问题(一直等待界面关闭)"""
#########################################################################################################
# 函数说明:napari.view_image(data, channel_axis=None, name=None, colormap=None, blending=None, interpolation=None, gamma=None, 
# is_pyramid=None, rgb=None, scale=None, translate=None, contrast_limits=None, rendering=None)
# 输入参数:
#       - data:要显示的图像数据。可以是以下格式之一:
#                 2D NumPy array:灰度图像数据。
#                 3D NumPy array:3D图像数据,例如多张2D图像叠加形成的图像序列。
#                 4D NumPy array:4D图像数据,例如多通道彩色图像。
#                 List of 2D, 3D, or 4D arrays:多个图像数据列表。
#                 Dask array:支持分块加载的大型图像数据。
#                 ImageData:来自dask_image.imread()等函数的图像数据对象。
#         channel_axis:用于多通道图像的通道轴的索引。默认值为None,表示使用最后一个轴作为通道轴。
#       - name:图像的名称,将在napari查看器中显示。
#       - colormap:图像的颜色映射。可以是字符串表示的颜色映射名称,或是colormap函数。默认值为None,表示使用默认颜色映射。
#         blending:图像的混合模式。可以是字符串表示的混合模式名称,例如"translucent"、"additive"等。默认值为None,表示使用默认混合模式。
#         interpolation:图像的插值方法。可以是字符串表示的插值方法名称,例如"nearest"、"bilinear"、"bicubic"等。默认值为None,表示使用默认插值方法。
#         gamma:图像的gamma值,用于对图像进行伽马校正。默认值为None,表示不进行伽马校正。
#         is_pyramid:布尔值,用于指示是否使用金字塔结构显示图像。默认值为None,表示不使用金字塔结构。
#         rgb:布尔值,用于指示输入图像是否为RGB彩色图像。默认值为None,表示根据输入图像数据自动判断。
#         scale:图像的缩放因子。可以是单个值,表示在所有轴上应用相同的缩放,也可以是每个轴的缩放因子列表。默认值为None,表示不进行缩放。
#         translate:图像的平移量。可以是单个值,表示在所有轴上应用相同的平移,也可以是每个轴的平移量列表。默认值为None,表示不进行平移。
#         contrast_limits:图像的对比度限制,用于控制图像显示的亮度范围。可以是单个值,表示在所有轴上应用相同的对比度限制,也可以是每个轴的对比度限制列表。默认值为None,表示不设置对比度限制。
#         rendering:图像的渲染模式。可以是字符串表示的渲染模式名称,例如"mip"、"translucent"、"attenuated_mip"等。默认值为None,表示使用默认渲染模式。
#########################################################################################################
"""

5.2、添加图像:viewer.add_image()

将单个或多个图像添加到napari查看器中,并提供了多个可选参数来自定义图像的显示。

在这里插入图片描述

import napari
import tifffileimage_path = '561result-1-part.tif'
marked_image = tifffile.imread(image_path)viewer = napari.Viewer()  # 创建napari视图
viewer.add_image(marked_image, name="image", colormap='red')  # 添加图像(指定红色)
################################################################################
# 隐藏面板
# viewer.window.qt_viewer.controls.hide()  # 隐藏后不可使用该功能(重新打开也不行)
# viewer.window.qt_viewer.layers.hide()# viewer.window.qt_viewer.controls.close()
# viewer.window.qt_viewer.layers.close()
################################################################################
napari.run()  # 显示napari图形界面
# 备注:若不添加napari.run(),将避免程序阻塞问题(一直等待界面关闭)"""
#########################################################################################################
# 函数说明:viewer.add_image(data, *, name=None, scale=None, translate=None, contrast_limits=None, 
#                          colormap=None, blending=None, visible=True, opacity=1.0, interpolation='bilinear', 
#                          rendering='mip', rgb=None, colormap_range=None)
# 输入参数:
#       - data:要添加的图像数据。可以是以下格式之一:
#                 2D NumPy array:灰度图像数据。
#                 3D NumPy array:3D图像数据,例如多张2D图像叠加形成的图像序列。
#                 4D NumPy array:4D图像数据,例如多通道彩色图像。
#       - name:图像的名称,将在napari查看器中显示。
#         scale:图像的缩放因子。可以是单个值,表示在所有轴上应用相同的缩放,也可以是每个轴的缩放因子列表。
#         translate:图像的平移量。可以是单个值,表示在所有轴上应用相同的平移,也可以是每个轴的平移量列表。
#         contrast_limits:图像的对比度限制,用于控制图像显示的亮度范围。可以是单个值,表示在所有轴上应用相同的对比度限制,也可以是每个轴的对比度限制列表。
#       - colormap:图像的颜色映射。可以是字符串表示的颜色映射名称,或是colormap函数。
#         blending:图像的混合模式。可以是字符串表示的混合模式名称,例如"translucent"、"additive"等。
#         visible:图像是否可见。布尔值,默认为True。
#         opacity:图像的不透明度。默认为1.0,表示完全不透明。
#         interpolation:图像的插值方法。可以是字符串表示的插值方法名称,例如"nearest"、"bilinear"、"bicubic"等。
#         rendering:图像的渲染模式。可以是字符串表示的渲染模式名称,例如"mip"、"translucent"、"attenuated_mip"等。
#         rgb:布尔值,用于指示输入图像是否为RGB彩色图像。
#         colormap_range:颜色映射的范围。可以是字符串,例如"auto"或"full",表示自动计算颜色映射范围或使用完整范围。
#########################################################################################################
"""

5.3、添加点云:viewer.add_points()

将点的坐标和可选的其他属性添加到napari查看器中,并提供了多个可选参数来自定义点云的显示。

  • viewer.add_points()用于添加点云数据,但不能直接显示。需要先添加viewer.view_image(),然后再显示点云数据。
  • 点云数据:由离散点(x, y, z)坐标的集合组成。

在这里插入图片描述

import napari
import tifffile
import numpy as np# (1)通过tifffile加载tif图像
marked_image = tifffile.imread('marked_image.tif')# (2)获取图像的长宽高
if len(marked_image.shape) == 3:  # 灰度3D图像:10x10x10depth, height, width = marked_image.shape
elif len(marked_image.shape) == 4:  # 彩色3D图像:3x10x10x10depth, height, width, _ = marked_image.shape# (3)根据图像类型自适应变量值
if marked_image.dtype == np.uint8:max_gray_value = 255
elif marked_image.dtype == np.uint16:max_gray_value = 65535
elif marked_image.dtype == np.uint32:max_gray_value = 4294967295
####################################################################
# (4.1)提取指定像素
indices = np.argwhere(marked_image == max_gray_value)# (4.2)指定范围内的像素值,获取坐标,并绘制为标记点
# min_gray_value = 50
# max_gray_value = max_gray_value - 1
# indices = np.argwhere((marked_image >= min_gray_value) & (marked_image <= max_gray_value))
####################################################################
viewer = napari.Viewer()  # 创建napari查看器
viewer.add_image(marked_image)  # 添加图像到napari视图
viewer.add_points(indices[:, [0, 1, 2]], size=2, face_color='red', shading='spherical', edge_width=0)  # 添加点云
napari.run()  # 显示napari图形界面
# 备注:若不添加napari.run(),将避免程序阻塞问题(一直等待界面关闭)

5.4、添加形状:viewer.add_shapes() —— 获取线条坐标(起点和终点)

注意:shapes层和image_data层是两个独立的层,故线的坐标映射到image_data需要进行高度和宽度限制。
在这里插入图片描述
在这里插入图片描述

import napari
import cv2# (1)加载图像
image_path = 'blank.png'
image_data = cv2.imread(image_path)
print("height:", image_data.shape[0], "width:", image_data.shape[1])
# (2)创建napari Viewer
viewer = napari.Viewer()
viewer.add_image(image_data)  # 添加图像
# 添加形状(线条 + 线宽 + 颜色)
shapes_layer = viewer.add_shapes(data=None, shape_type='line', edge_width=3, edge_color='red')  
shapes_layer.mode = 'add_line'  # 直接开始绘制线条
napari.run()  # 运行napari
# 备注:若不添加napari.run(),将避免程序阻塞问题(一直等待界面关闭)# (3)打印坐标
# image_shape = image_data.shape  # 获取图像的形状
line_layer = viewer.layers['Shapes']  # 获取绘制的线的图层
line_coordinates1 = []  # 获取绘制的所有线的坐标
line_coordinates2 = []  # 获取绘制的所有线的坐标:删除超出图像的线条if line_layer.data:  # 检查图层数据是否存在for line in line_layer.data:  # 遍历线的坐标coordinates1 = [line[0, 0], line[0, 1], line[1, 0], line[1, 1]]line_coordinates1.append(coordinates1)for line in line_layer.data:  # 遍历线的坐标# 【高度限制】:删除超出图像的线条if line[0, 0] < 0:line[0, 0] = 0elif line[0, 0] > image_data.shape[0]:line[0, 0] = image_data.shape[0]if line[1, 0] < 0:line[1, 0] = 0elif line[1, 0] > image_data.shape[0]:line[1, 0] = image_data.shape[0]# 【宽度限制】:删除超出图像的线条if line[0, 1] < 0:line[0, 1] = 0elif line[0, 1] > image_data.shape[1]:line[0, 1] = image_data.shape[1]if line[1, 1] < 0:line[1, 1] = 0elif line[1, 1] > image_data.shape[1]:line[1, 1] = image_data.shape[1]coordinates2 = [line[0, 0], line[0, 1], line[1, 0], line[1, 1]]line_coordinates2.append(coordinates2)# 输出所有坐标(shapes:线坐标)for idx, coordinates in enumerate(line_coordinates1):print(f'Line {idx + 1} coordinates1:', coordinates)print("")# 输出所有坐标(image:线坐标映射到图像的坐标):高度限制+宽度限制for idx, coordinates in enumerate(line_coordinates2):print(f'Line {idx + 1} coordinates2:', coordinates)

六、在napari中自定义组件,并与PyQt完成交互

在napari中自定义组件与PyQt新建组件的方法相同,区别是需要将插件的主窗口添加到napari界面的控制面板中:self.viewer.window.add_dock_widget(widget, area='right') # 添加到napari的右侧,其中:widget是插件的主窗口。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import tifffile
import napari
import numpy as np
import sys
import os
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, \QPushButton, QFileDialog, QTextEdit, QSlider, QCheckBox
from PyQt5.QtCore import Qtclass Window(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("Window")##########################################################layout = QVBoxLayout()button_layout = QHBoxLayout()self.load_button = QPushButton("Load Image", self)self.load_button.clicked.connect(self.load_image)self.image_name_label = QLabel("")button_layout.addWidget(self.load_button)button_layout.addWidget(self.image_name_label)layout.addLayout(button_layout)##########################################################widget = QWidget()widget.setLayout(layout)self.setCentralWidget(widget)########################################################### 初始化参数self.image_path = ""self.image_name = ""##########################################################def load_image(self):file_dialog = QFileDialog()image_path, _ = file_dialog.getOpenFileName(self, "Select Image", "", "Image Files (*.tif *.png *.jpg *.jpeg)")if image_path:self.image_path = image_pathself.image_name = os.path.basename(image_path)self.image_name_label.setText(self.image_name)self.image_slices = tifffile.imread(image_path)self.napari_gray_view()  # 调用napari_gray_view方法来显示第一个切片def napari_gray_view(self):# (1)napari:创建视图、添加图层、显示视图self.viewer = napari.Viewer()  # 创建napari视图self.viewer.add_image(self.image_slices, name='image')  # 添加napari图层# napari.run()  # 显示napari图形界面# 备注:若不添加napari.run(),将避免程序阻塞问题(一直等待界面关闭)########################################################################## (2)自定义组件########################################################################## (2.1)创建滑动条self.slider = QSlider()  # 新建滑动条self.slider.setMinimum(0)  # 设置滑动条的最小值self.slider.setMaximum(np.max(self.image_slices))  # 设置滑动条的最大值self.slider.setValue(0)  # 设置滑动条的初始值# (2.2)创建标签self.slider_label = QLabel(str(self.slider.value()))# (2.3)复选框self.checkbox = QCheckBox("checkbox")  # 复选框self.slider.setEnabled(False)  # 复选框的初始状态:Falseself.input_box = QLineEdit()  # 新建输入框self.input_box.setEnabled(True)  # 复选框的初始状态:Trueself.input_label = QLabel("range: " + str(np.min(self.image_slices)) + "/" + str(np.max(self.image_slices)))  # 输入框标签# (3)创建布局并将滑动条和标签添加到布局中layout = QVBoxLayout()layout.addWidget(self.slider)layout.addWidget(self.slider_label)layout.addWidget(self.checkbox)layout.addWidget(self.input_box)layout.addWidget(self.input_label)# (4)创建一个QWidget作为插件的主窗口widget = QWidget()widget.setLayout(layout)# (5)连接复选框的状态变化信号与槽函数self.checkbox.stateChanged.connect(self.onCheckboxStateChanged)self.slider.valueChanged.connect(self.napari_update_gray)  # 根据滑动条的值,显示第一个切片self.input_box.returnPressed.connect(self.napari_update_gray)  # 根据输入框的值,显示第一个切片# (6)将插件的主窗口添加到napari界面的控制面板中self.viewer.window.add_dock_widget(widget, area='right')  # 添加到napari的右侧########################################################################## (7)napari:显示视图self.viewer.window.show()def onCheckboxStateChanged(self, state):if state == Qt.Checked:self.slider.setEnabled(True)self.input_box.setEnabled(False)else:self.slider.setEnabled(False)self.input_box.setEnabled(True)def napari_update_gray(self):# (1)获取napari视图中的图层对象,并获取图像数据napari_image = self.image_slices.data# (2)获取当前切片滑动条的值current_slice = int(self.viewer.dims.current_step[0])# (3)获取当前灰度滑动条的值self.slider_label.setText(str(self.slider.value()))if self.checkbox.isChecked():current_gray = self.slider.value()else:current_gray = int(self.input_box.text())print("current_slice:", current_slice, "current_gray:", current_gray)if __name__ == '__main__':app = QApplication(sys.argv)window = Window()window.show()sys.exit(app.exec_())

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

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

相关文章

Linux学习之Telnet明文漏洞

yum install telnet telnet-server xinetd -y安装软件。 systemctl start xinetd.service开启xinetd&#xff0c;systemctl start telnet.socket开启telnet。 xinetd来监控端口&#xff0c;然后把数据传给telnet。 ifconfig eth0看一下eth0网卡信息&#xff0c;。 iptable…

Linux Mint 21.3 计划于 2023 年圣诞节发布

Linux Mint 项目近日公布了基于 Ubuntu 的 Linux Mint 发行版下一个重要版本的一些初步细节&#xff0c;以及备受期待的基于 Debian 的 LMDE 6&#xff08;Linux Mint Debian Edition&#xff09;版本。 近日&#xff0c;Linux Mint 项目负责人克莱门特-勒菲弗&#xff08;Clem…

万字长文·通俗易懂·一篇包掌握——输入/输出·文件操作(c语言超详细系列)(二)

前言&#xff1a;Hello&#xff0c;大家好&#x1f618;&#xff0c;我是心跳sy&#xff0c;上一节我们主要学习了格式化输入输出的基本内容&#xff0c;这一节我们对格式化进行更加深入的了解&#xff0c;对文件概念进行介绍&#xff0c;并且对输入、输出与文件读写的基本概念…

基于 KubeSphere 的应用容器化在智能网联汽车领域的实践

公司简介 某国家级智能网联汽车研究中心成立于 2018 年&#xff0c;是担当产业发展咨询与建议、共性技术研发中心、创新成果转化的国家级创新平台&#xff0c;旨在提高我国在智能网联汽车及相关产业在全球价值链中的地位。 目前着力建设基于大数据与云计算的智能汽车云端运营…

[bug] 记录version `GLIBCXX_3.4.29‘ not found 解决方法

在使用mediapipe 这个库的时候&#xff0c;首次使用出现 GLIBCXX_3.4.29’ not found 错误&#xff0c; 看起来是安装mediapipe 的时候自动升级了 matplotlib 这个库&#xff0c;导致依赖的 libstd.so 版本不满足了&#xff0c;GLIBCXX_3.4.29 is an object from libstdc.so.…

Debian10: 安装nut服务器(UPS)

UPS说明&#xff1a; UPS的作用就不必讲了&#xff0c;我选择是SANTAKTGBOX-850&#xff0c;规格为 850VA/510W&#xff0c;可以满足所需&#xff0c;关键是Debian10自带了驱动可以支持&#xff0c;免去安装驱动&#xff0c;将UPS通过USB线连接服务器即可&#xff0c;如下图所示…

【数理知识】向量与基的内积,Matlab 代码验证

序号内容1【数理知识】向量的坐标基表示法&#xff0c;Matlab 代码验证2【数理知识】向量与基的内积&#xff0c;Matlab 代码验证 文章目录 1. 向量与基的内积2. 二维平面向量举例3. 代码验证Ref 1. 向量与基的内积 假设存在一个二维平面内的向量 a ⃗ \vec{a} a &#xff0c…

QT TLS initialization failed问题(已解决) QT基础入门【网络编程】openssl

问题: qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed 这个问题的出现主要是使用了https请求:HTTPS ≈ HTTP + SSL,即有了加密层的HTTP 所以Qt 组件库需要OpenSSL dll 文件支持HTTPS 解决: 1.加入以下两行代码获取QT是否支持opensll以…

【学习FreeRTOS】第8章——FreeRTOS列表和列表项

1.列表和列表项的简介 列表是 FreeRTOS 中的一个数据结构&#xff0c;概念上和链表有点类似&#xff0c;列表被用来跟踪 FreeRTOS中的任务。列表项就是存放在列表中的项目。 列表相当于链表&#xff0c;列表项相当于节点&#xff0c;FreeRTOS 中的列表是一个双向环形链表列表的…

@Repeatable的作用以及具体如何使用

文章目录 1. 前言2. 先说结论3. 案例演示 1. 前言 最近无意看到某些注解上有Repeatable&#xff0c;出于比较好奇&#xff0c;因此稍微研究并写下此文章。 2. 先说结论 Repeatable的作用&#xff1a;使被他注释的注解可以在同一个地方重复使用。 具体使用如下&#xff1a; T…

.netcore grpc客户端工厂及依赖注入使用

一、客户端工厂概述 gRPC 与 HttpClientFactory 的集成提供了一种创建 gRPC 客户端的集中方式。可以通过依赖包Grpc.Net.ClientFactory中的AddGrpcClient进行gRPC客户端依赖注入AddGrpcClient函数提供了许多配置项用于处理一些其他事项&#xff1b;例如AOP、重试策略等 二、案…

【100天精通python】Day41:python网络爬虫开发_爬虫基础入门

目录 专栏导读 1网络爬虫概述 1.1 工作原理 1.2 应用场景 1.3 爬虫策略 1.4 爬虫的挑战 2 网络爬虫开发 2.1 通用的网络爬虫基本流程 2.2 网络爬虫的常用技术 2.3 网络爬虫常用的第三方库 3 简单爬虫示例 专栏导读 专栏订阅地址&#xff1a;https://blog.csdn.net/…

Databend 开源周报第 106 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 数据脱敏 Data…

APSIM模型参数优化 批量模拟丨气象数据准备、物候发育和光合生产、物质分配与产量模拟、土壤水分平衡算法、土壤碳氮平衡模块、农田管理模块等

随着数字农业和智慧农业的发展&#xff0c;基于过程的农业生产系统模型在模拟作物对气候变化的响应与适应、农田管理优化、作物品种和株型筛选、农田固碳和温室气体排放等领域扮演着越来越重要的作用。APSIM (Agricultural Production Systems sIMulator)模型是世界知名的作物生…

nginx php-fpm安装配置

nginx php-fpm安装配置 nginx本身不能处理PHP&#xff0c;它只是个web服务器&#xff0c;当接收到请求后&#xff0c;如果是php请求&#xff0c;则发给php解释器处理&#xff0c;并把结果返回给客户端。 nginx一般是把请求发fastcgi管理进程处理&#xff0c;fascgi管理进程选…

6.RocketMQ之索引文件ConsumeQueue

本文着重分析为consumequeue/topic/queueId目录下的索引文件。 1.ConsumeQueueStore public class ConsumeQueueStore {protected final ConcurrentMap<String>, ConcurrentMap<Integer>, ConsumeQueueInterface>> consumeQueueTable;public boolean load(…

Sentinel 规则持久化

文章目录 Sentinel 规则持久化一、修改order-service服务1.引入依赖2.配置nacos地址 第二步修改非常麻烦&#xff0c;可以略过&#xff0c;直接使用已经打好包的来使用二、修改sentinel-dashboard源码1. 解压2. 修改nacos依赖3. 添加nacos支持4. 修改nacos地址5. 配置nacos数据…

micropython SSD1306/SSD1315驱动

目录 简介 代码 功能 显示ASCII字符 ​编辑 画任意直线 画横线 画竖线 画矩形 画椭圆 画立方体 画点阵图 翻转 反相 滚动 横向滚动 纵向滚动 奇葩滚动 简介 我重新写了一个驱动&#xff0c;增加了一些功能&#xff0c;由于我的硬件是128*64oled单色I2C&#xff0c;我只…

Hlang--用Python写个编程语言-判断与循环

文章目录 前言语法描述判断循环词法解析语法解析定义节点生成节点判断节点循环节点解释器处理判断节点循环处理前言 okey,很好,在上一篇文章当中,我们实现了这个基本的逻辑运算,所以的话,在这里,我们将可以实现到我们的这个判断和循环了。由于这里的话,我们的操作其实和…

UML图绘制 -- 类图

1.类图的画法 类 整体是个矩形&#xff0c;第一层类名&#xff0c;第二层属性&#xff0c;第三层方法。 &#xff1a;public- : private# : protected空格: 默认的default 对应的类写法。 public class Student {public String name;public Integer age;protected I…