【Python语义分割】Segment Anything(SAM)模型全局语义分割代码+掩膜保存(二)

news2024/11/15 23:20:52

我上篇博文分享了Segment Anything(SAM)模型的基本操作,这篇给大家分享下官方的整张图片的语义分割代码(全局),同时我还修改了一部分支持掩膜和叠加影像的保存。

1 Segment Anything介绍

1.1 概况

        Meta AI 公司的 Segment Anything 模型是一项革命性的技术,该模型能够根据文本指令或图像识别,实现对任意物体的识别和分割。这一模型的推出,将极大地推动计算机视觉领域的发展,并使得图像分割技术进一步普及化。

        论文地址:https://arxiv.org/abs/2304.02643

        项目地址:Segment Anything

1.2 使用方法

        具体使用方法上,Segment Anything 提供了简单易用的接口,用户只需要通过提示,即可进行物体识别和分割操作。例如在图片处理中,用户可以通过 Hover & Click 或 Box 等方式来选取物体。值得一提的是,SAM 还支持通过上传自己的图片进行物体分割操作,提取物体用时仅需数秒。

        总的来说,Meta AI 的 Segment Anything 模型为我们提供了一种全新的物体识别和分割方式,其强大的泛化能力和广泛的应用前景将极大地推动计算机视觉领域的发展。未来,我们期待看到更多基于 Segment Anything 的创新应用,以及在科学图像分析、照片编辑等领域的广泛应用。

​​2 模型代码+注释

2.1 模型预加载

        我这里将掩膜生成的函数单独拿出来了,因为里面集成了掩膜保存的代码。所以先给大家看预处理部分。

    try:
        image = cv2.imread(image_path)  # 读取的图像以NumPy数组的形式存储在变量image中
        print("[%s]正在转换图片格式......" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  # 将图像从BGR颜色空间转换为RGB颜色空间,还原图片色彩(图像处理库所认同的格式)
        print("[%s]正在初始化模型参数......" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    except:
        print("图片打开失败!请检查路径!")
        pass
        sys.exit()
    sys.path.append("..")  # 将当前路径上一级目录添加到sys.path列表,这里模型使用绝对路径所以这行没啥用
    sam_checkpoint = model_path  # 定义模型路径

    sam = sam_model_registry[model_type](checkpoint=sam_checkpoint)
    sam.to(device=device)  # 定义模型参数
    mask_generator = SamAutomaticMaskGenerator(model=sam,  # 用于掩膜预测的SAM模型
                                               points_per_side=32,  # 图像一侧的采样点数,总采样点数是一侧采样点数的平方,点数给的越多,分割越细
                                               # points_per_batch=64,  # 设置模型同时运行的点的数量。更高的数字可能会更快,但会使用更多的GPU内存
                                               pred_iou_thresh=0.86,  # 滤波阈值,在[0,1]中,使用模型的预测掩膜质量0.86
                                               stability_score_thresh=0.92,
                                               # 滤波阈值,在[0,1]中,使用掩码在用于二进制化模型的掩码预测的截止点变化下的稳定性0.92
                                               # stability_score_offset=1.0,  # 计算稳定性分数时,对截止点的偏移量
                                               # box_nms_thresh=0.7,  # 非最大抑制用于过滤重复掩码的箱体IoU截止点
                                               crop_n_layers=1,  # 如果>0,蒙版预测将在图像的裁剪上再次运行。设置运行的层数,其中每层有2**i_layer的图像裁剪数1
                                               # crop_nms_thresh=0.7,  # 非最大抑制用于过滤不同作物之间的重复掩码的箱体IoU截止值
                                               # crop_overlap_ratio=512 / 1500,  # 设置作物重叠的程度
                                               crop_n_points_downscale_factor=2,
                                               # 在图层n中每面采样的点数被crop_n_points_downscale_factor**n缩减2
                                               # point_grids=None,  # 用于取样的明确网格的列表,归一化为[0,1]
                                               min_mask_region_area=100,
                                               # 如果>0,后处理将被应用于移除面积小于min_mask_region_area的遮罩中的不连接区域和孔。需要opencv。50
                                               # output_mode="binary_mask"  # 掩模的返回形式。
                                               # 可以是’binary_mask’, ‘uncompressed_rle’, 或者’coco_rle’。
                                               # coco_rle’需要pycocotools。对于大的分辨率,'binary_mask’可能会消耗大量的内存
                                               )  # 激活函数

2.2 模型预测代码

masks = mask_generator.generate(image)  # 类别掩膜提取(包含所有的,可按照索引查看)

# ---------------------------masks输出内容---------------------------
# segmentation : np的二维数组,为二值的mask图片
# area : mask的像素面积
# bbox : mask的外接矩形框,为X Y WH格式
# predicted_iou : 该mask的质量(模型预测出的与真实框的iou)
# point_coords : 用于生成该mask的point输入
# stability_score : mask质量的附加指标
# crop_box : 用于以X Y WH格式生成此遮罩的图像裁剪
# ------------------------------------------------------------------

print("[%s]正在绘制图片......" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
plt.figure(figsize=(20, 20))  # 创建一个新的图形窗口,设置其大小为10x10英寸
plt.imshow(image)  # 使用imshow函数在创建的图形窗口中显示图像
print("[%s]正在制作掩膜......" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
print("【结果保存阶段】")
show_mask_auto(masks, out_path, out_path1)
plt.axis('on')  # 开启图像坐标轴,使得图像下的像素坐标可以显示出来
print("[%s]正在保存叠加结果......" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
plt.savefig(out_image_path, dpi=300)
plt.show()  # 显示已经创建的图形窗口和其中的内容

2.3 掩膜生成+保存代码

        我这里在官方的掩膜生成的函数的基础上,加入了两段保存数据的代码。一个是彩色的mask(叠加显示的mask),一个是单波段的mask(DN值代表序号)。

        大家在使用这个函数时,将这段放在2.1,2.2展示的代码前面即可。

def show_mask_auto(masks_data, out_mask_path, out_path_01):
    """
    :param masks_data: 掩膜数据
    :param out_mask_path: 输出彩色掩膜
    :param out_path_01: 输出单波段掩膜
    :return: None
    """
    if len(masks_data) == 0:
        return
    sorted_masks_data = sorted(masks_data, key=(lambda x: x['area']), reverse=True)  # 按照面积大小降序排列
    ax = plt.gca()  # 获取当前的轴(axes)
    ax.set_autoscale_on(False)  # 关闭轴的自动缩放功能
    img = np.ones((sorted_masks_data[0]['segmentation'].shape[0], sorted_masks_data[0]['segmentation'].shape[1], 4))
    # 创建了一个新的三维数组img。数组的形状是基于segmentation']的形状,其中四个通道通常代表红色、绿色、蓝色和透明度(RGBA)
    img[:, :, 3] = 0  # 将新创建的图像的第四个通道(也就是透明度通道)设置为0
    img_raster = np.zeros((sorted_masks_data[0]['segmentation'].shape[0],
                          sorted_masks_data[0]['segmentation'].shape[1]))
    # 创建一个二维数组,用于保存掩膜做栅格转面
    j = 1
    for sorted_mask_data in sorted_masks_data:
        # 循环所有类别的掩膜
        m = sorted_mask_data['segmentation']
        # 获取当前类别的二值mask图片
        color_mask = np.concatenate([np.random.random(3), [0.65]])
        # 随机生成的RGB颜色,它的形状为(3,),0.65表示颜色的透明度。
        img[m] = color_mask
        # 将颜色赋予图片的数组
        img_raster[m] = j
        # 给掩膜赋值
        j += 1
    """for i in range(0, len(masks_data)):
        # 循环所有类别的掩膜
        rect = patches.Rectangle((masks_data[i]['bbox'][0], masks_data[i]['bbox'][1]), masks_data[i]['bbox'][2],
                                 masks_data[i]['bbox'][3], edgecolor=tuple(random.uniform(0, 1) for _ in range(3)),
                                 facecolor='none', linewidth=2)  # 绘制类别的外接矩形框
        ax.add_patch(rect)  # 将矩形添加到ax对象中"""
    plt.imshow(img, alpha=0.8)
    print("[%s]正在保存类别掩膜......" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    driver = gdal.GetDriverByName('GTiff')  # 载入数据驱动,用于存储内存中的数组
    ds_result = driver.Create(out_mask_path, sorted_masks_data[0]['segmentation'].shape[1],
                              sorted_masks_data[0]['segmentation'].shape[0], bands=4, eType=gdal.GDT_Float64)
    # 创建一个数组,宽高为原始尺寸
    for i in range(3):
        ds_result.GetRasterBand(i+1).SetNoDataValue(0)  # 将无效值设为0
        ds_result.GetRasterBand(i+1).WriteArray(img[:, :, i])  # 将结果写入数组
    ds_result_raster = driver.Create(out_path_01, sorted_masks_data[0]['segmentation'].shape[1],
                                     sorted_masks_data[0]['segmentation'].shape[0], bands=1, eType=gdal.GDT_Float64)
    # ds_result.SetGeoTransform(ds_geo)  # 导入仿射地理变换参数
    # ds_result.SetProjection(ds_prj)  # 导入投影信息
    ds_result_raster.GetRasterBand(1).SetNoDataValue(0)  # 将无效值设为0
    ds_result_raster.GetRasterBand(1).WriteArray(img_raster)  # 将结果写入数组
    del ds_result
    del ds_result_raster

3 完整代码

# -*- coding: utf-8 -*-
"""
@Time : 2023/10/8 10:15
@Auth : RS迷途小书童
@File :Segment Anything Auto.py
@IDE :PyCharm
@Purpose:Segment Anything Model自动全局语义分割
"""
import sys
import cv2
import random
import numpy as np
from osgeo import gdal
from datetime import datetime
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from segment_anything import sam_model_registry, SamAutomaticMaskGenerator


def SAM_auto(image_path, model_path, model_type, device, out_path, out_path1, out_image_path):
    """
    :param image_path: 输入需要分割的影像
    :param model_path: 输入模型路径
    :param model_type: 输入模型类型
    :param device: 输入cpu or cuda
    :param out_path: 输出彩色掩膜文件
    :param out_path1: 输出单波段掩膜文件
    :param out_image_path: 输出叠加图片
    :return: None
    """

    def show_mask_auto(masks_data, out_mask_path, out_path_01):
        """
        :param masks_data: 掩膜数据
        :param out_mask_path: 输出彩色掩膜
        :param out_path_01: 输出单波段掩膜
        :return: None
        """
        if len(masks_data) == 0:
            return
        sorted_masks_data = sorted(masks_data, key=(lambda x: x['area']), reverse=True)  # 按照面积大小降序排列
        ax = plt.gca()  # 获取当前的轴(axes)
        ax.set_autoscale_on(False)  # 关闭轴的自动缩放功能
        img = np.ones((sorted_masks_data[0]['segmentation'].shape[0], sorted_masks_data[0]['segmentation'].shape[1], 4))
        # 创建了一个新的三维数组img。数组的形状是基于segmentation']的形状,其中四个通道通常代表红色、绿色、蓝色和透明度(RGBA)
        img[:, :, 3] = 0  # 将新创建的图像的第四个通道(也就是透明度通道)设置为0
        img_raster = np.zeros((sorted_masks_data[0]['segmentation'].shape[0],
                              sorted_masks_data[0]['segmentation'].shape[1]))
        # 创建一个二维数组,用于保存掩膜做栅格转面
        j = 1
        for sorted_mask_data in sorted_masks_data:
            # 循环所有类别的掩膜
            m = sorted_mask_data['segmentation']
            # 获取当前类别的二值mask图片
            color_mask = np.concatenate([np.random.random(3), [0.65]])
            # 随机生成的RGB颜色,它的形状为(3,),0.65表示颜色的透明度。
            img[m] = color_mask
            # 将颜色赋予图片的数组
            img_raster[m] = j
            # 给掩膜赋值
            j += 1
        """for i in range(0, len(masks_data)):
            # 循环所有类别的掩膜
            rect = patches.Rectangle((masks_data[i]['bbox'][0], masks_data[i]['bbox'][1]), masks_data[i]['bbox'][2],
                                     masks_data[i]['bbox'][3], edgecolor=tuple(random.uniform(0, 1) for _ in range(3)),
                                     facecolor='none', linewidth=2)  # 绘制类别的外接矩形框
            ax.add_patch(rect)  # 将矩形添加到ax对象中"""
        plt.imshow(img, alpha=0.8)
        print("[%s]正在保存类别掩膜......" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        driver = gdal.GetDriverByName('GTiff')  # 载入数据驱动,用于存储内存中的数组
        ds_result = driver.Create(out_mask_path, sorted_masks_data[0]['segmentation'].shape[1],
                                  sorted_masks_data[0]['segmentation'].shape[0], bands=4, eType=gdal.GDT_Float64)
        # 创建一个数组,宽高为原始尺寸
        for i in range(3):
            ds_result.GetRasterBand(i+1).SetNoDataValue(0)  # 将无效值设为0
            ds_result.GetRasterBand(i+1).WriteArray(img[:, :, i])  # 将结果写入数组
        ds_result_raster = driver.Create(out_path_01, sorted_masks_data[0]['segmentation'].shape[1],
                                         sorted_masks_data[0]['segmentation'].shape[0], bands=1, eType=gdal.GDT_Float64)
        # ds_result.SetGeoTransform(ds_geo)  # 导入仿射地理变换参数
        # ds_result.SetProjection(ds_prj)  # 导入投影信息
        ds_result_raster.GetRasterBand(1).SetNoDataValue(0)  # 将无效值设为0
        ds_result_raster.GetRasterBand(1).WriteArray(img_raster)  # 将结果写入数组
        del ds_result
        del ds_result_raster

    print("【程序准备阶段】")
    print("[%s]正在读取图片......" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    try:
        image = cv2.imread(image_path)  # 读取的图像以NumPy数组的形式存储在变量image中
        print("[%s]正在转换图片格式......" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  # 将图像从BGR颜色空间转换为RGB颜色空间,还原图片色彩(图像处理库所认同的格式)
        print("[%s]正在初始化模型参数......" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    except:
        print("图片打开失败!请检查路径!")
        pass
        sys.exit()
    sys.path.append("..")  # 将当前路径上一级目录添加到sys.path列表,这里模型使用绝对路径所以这行没啥用
    sam_checkpoint = model_path  # 定义模型路径

    sam = sam_model_registry[model_type](checkpoint=sam_checkpoint)
    sam.to(device=device)  # 定义模型参数
    mask_generator = SamAutomaticMaskGenerator(model=sam,  # 用于掩膜预测的SAM模型
                                               points_per_side=32,  # 图像一侧的采样点数,总采样点数是一侧采样点数的平方,点数给的越多,分割越细
                                               # points_per_batch=64,  # 设置模型同时运行的点的数量。更高的数字可能会更快,但会使用更多的GPU内存
                                               pred_iou_thresh=0.86,  # 滤波阈值,在[0,1]中,使用模型的预测掩膜质量0.86
                                               stability_score_thresh=0.92,
                                               # 滤波阈值,在[0,1]中,使用掩码在用于二进制化模型的掩码预测的截止点变化下的稳定性0.92
                                               # stability_score_offset=1.0,  # 计算稳定性分数时,对截止点的偏移量
                                               # box_nms_thresh=0.7,  # 非最大抑制用于过滤重复掩码的箱体IoU截止点
                                               crop_n_layers=1,  # 如果>0,蒙版预测将在图像的裁剪上再次运行。设置运行的层数,其中每层有2**i_layer的图像裁剪数1
                                               # crop_nms_thresh=0.7,  # 非最大抑制用于过滤不同作物之间的重复掩码的箱体IoU截止值
                                               # crop_overlap_ratio=512 / 1500,  # 设置作物重叠的程度
                                               crop_n_points_downscale_factor=2,
                                               # 在图层n中每面采样的点数被crop_n_points_downscale_factor**n缩减2
                                               # point_grids=None,  # 用于取样的明确网格的列表,归一化为[0,1]
                                               min_mask_region_area=100,
                                               # 如果>0,后处理将被应用于移除面积小于min_mask_region_area的遮罩中的不连接区域和孔。需要opencv。50
                                               # output_mode="binary_mask"  # 掩模的返回形式。
                                               # 可以是’binary_mask’, ‘uncompressed_rle’, 或者’coco_rle’。
                                               # coco_rle’需要pycocotools。对于大的分辨率,'binary_mask’可能会消耗大量的内存
                                               )  # 激活函数
    print("【模型预测阶段】")
    print("[%s]正在分割图片......" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    masks = mask_generator.generate(image)  # 类别掩膜提取(包含所有的,可按照索引查看)

    # ---------------------------masks输出内容---------------------------
    # segmentation : np的二维数组,为二值的mask图片
    # area : mask的像素面积
    # bbox : mask的外接矩形框,为X Y WH格式
    # predicted_iou : 该mask的质量(模型预测出的与真实框的iou)
    # point_coords : 用于生成该mask的point输入
    # stability_score : mask质量的附加指标
    # crop_box : 用于以X Y WH格式生成此遮罩的图像裁剪
    # ------------------------------------------------------------------

    print("[%s]正在绘制图片......" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    plt.figure(figsize=(20, 20))  # 创建一个新的图形窗口,设置其大小为10x10英寸
    plt.imshow(image)  # 使用imshow函数在创建的图形窗口中显示图像
    print("[%s]正在制作掩膜......" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    print("【结果保存阶段】")
    show_mask_auto(masks, out_path, out_path1)
    plt.axis('on')  # 开启图像坐标轴,使得图像下的像素坐标可以显示出来
    print("[%s]正在保存叠加结果......" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    plt.savefig(out_image_path, dpi=300)
    plt.show()  # 显示已经创建的图形窗口和其中的内容
    print("-----------------------------------------语义分割已完成----------------------------------------")


if __name__ == "__main__":
    print("\n")
    print("--------------------------------------Segment Anything--------------------------------------")
    Image_path = r'B:/Personal/satellite.tif'  # 分割的影像
    Model_path = "G:/Neat Download Manager/Misc/sam_vit_h_4b8939.pth"  # 模型路径
    Out_mask_path = 'B:/Personal/my_figure1.tif'  # 彩色掩膜
    Out_mask_path1 = 'B:/Personal/my_figure2.tif'  # 二维掩膜用于转矢量
    Out_image_path = 'B:/Personal/my_figure3.png'  # 叠加结果
    Model_type = "vit_h"  # 定义模型类型
    Device = "cuda"  # "cpu"  or  "cuda"
    SAM_auto(Image_path, Model_path, Model_type, Device, Out_mask_path, Out_mask_path1, Out_image_path)
    # 图片,模型,类型,算力,彩色掩膜,黑白掩膜,叠加图片

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

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

相关文章

201、RabbitMQ 之 Exchange 典型应用模型 之 工作队列(Work Queue)

目录 ★ 工作队列介绍代码演示测试注意点1:注意点2: ★ 工作队列介绍 工作队列: 就是让多个消费者竞争消费同一个消息队列的消息,相当于多个消费者共享消息队列。 ▲ RabbitMQ可以让多个消费者竞争消费同一个消息队列 ▲ 消息队…

MS4344:24bit、192kHz 双通道数模转换电路

MS4344 是一款立体声数模转换芯片,内含插值滤波器、 multi-bit 数模转换器、输出模拟滤波器。 MS4344 支持大部分 的音频数据格式。 MS4344 基于一个带线性模拟低通滤波器的 四阶 multi-bit Δ-Σ 调制器,而且本芯片可以通过检测信号频率 和主时钟频…

【Axure高保真原型】冻结固定中继器表格首行+首尾列

今天和大家分享冻结固定中继器表格首行首尾列的原型模板,我们可以滚动或者拖动滚动条上下左右查看表格更多的数据,表格的首行和首尾两列都是固定的,鼠标移入对应行会有高亮显示的效果,点击操作列的删除按钮可以删除该行数据。那这…

智能油烟机 优化烹饪体验

如果说空调是夏天最伟大的发明,那么油烟机则是健康厨房的伟大推进者。随着科技的发展,智能化的油烟机逐渐走进了人们的日常生活。每当我们在爆炒、油炸食物的时候,油烟总能呛得人眼睛痛、鼻子难受,传统的油烟机面前我们还需要手动…

蒙自源荣登“2022年度中国快餐TOP100”榜单!

2023年9月26日,由中国烹饪协会主办的第27届中国快餐产业大会在浙江宁波盛大召开。 对于行业而言,这是一次至关重要的聚会。本次大会以“增量博弈,智造无限机遇”为主题,聚集了众多餐饮业的意见领袖,共同探讨行业发展焦…

第二证券:市净率高好还是低好?

市净率是一个衡量公司股票投资价值的指标,通过比较公司股票价格和公司每股净资产的比值来评估公司股票的估值水平。市净率高好还是低好这个问题并没有一个简单的答案,取决于具体的市场环境和投资者的需求。本文将从多个角度分析市净率高好还是低好。 首…

云HIS医院信息化管理平台源码,SaaS模式、springboot框架

HIS系统作为医院信息化的核心业务系统,如今已成为各个医疗机构的必备品了。大到三级二级医院,小到社区卫生服务中心,门诊(门诊管理系统也可以理解为门诊的his系统,只是功能简单,模块较少)。随着…

STM32F103C8T6一些集成模块(ADC)

ADC ADC,Analog-to-Digital Converter的缩写,指模/数转换器或者模数转换器 [1] 。是指将连续变化的模拟信号转换为离散的数字信号的器件。真实世界的模拟信号,例如温度、压力、声音或者图像等,需要转换成更容易储存、处理和发射的…

Git 速通以及常用指令!!

参考视频 01 - Git - 教程简介_哔哩哔哩_bilibili 在需要使用git的文件夹打开git bash,指令如下↓ 当然图形化界面也很香!github desktop也很舒服! 查看文件 版本号 git cat-file -p 版本号 仓库操作 在当前文件夹下创建git仓库 git ini…

轻量级Composition

MEF,全称Managed Extensibility Framework(托管可扩展框架)。MEF是专门致力于解决扩展性问题的框架。MEF 位于 ComponentModel.Composition 程序集中,添加 System.ComponentModel.Composition 和 System.ComponentModel.Compositi…

是谁制造了TikTok的商业化困境?

随着社交媒体的崭露头角,TikTok已成为数字营销界备受瞩目的新星。这款以短视频为特色的应用程序在全球范围内拥有数亿用户,吸引了众多品牌和创业者的关注。 然而,尽管TikTok拥有巨大的用户基础和潜力,但它也面临着商业化方面的一…

如何在会计面试中展现自己的优势?

在会计面试中展现自己的优势是非常重要的,因为这将决定你是否能够脱颖而出并获得这个职位。下面是一些可以帮助你展示自己优势的方法: 1. 准备充分:在面试前,确保你对公司的背景和业务有所了解。研究公司的财务报告和新闻&#xf…

搞流式计算,大厂也没有什么神话

抖音、今日头条,是字节跳动旗下最受用户欢迎的两款产品,也是字节跳动的门面。而在这背后,是众多技术团队在支撑,流式计算就是其中一支。 不过,即使是在字节跳动,搞流式计算也没有神话。只有一群年轻人&…

软件测试学习(二)静态白盒测试、动态白盒测试、配置测试、兼容性测试、外国语言测试

静态白盒测试:检查设计和代码 静态是指不启动,白盒是指看内部代码。 静态白盒测试是在不执行软件的条件下有条理地仔细审查软件设计、体系结构和代码,从而找出软件缺陷的过程,有时称为结构化分析。 进行静态白盒测试的首要原因是尽…

使用antd-pro脚手架搭建react ts项目

Pro 中使用 TypeScript 来作为默认的开发语言,TypeScript 的好处已经无须赘述,无论是开发成本还是维护成本都能大大减少,是中后台开发的必选。 初始化 提供了 pro-cli 来快速的初始化脚手架。 # 使用 npm npm i ant-design/pro-cli -g pro…

生产级Stable Diffusion AI服务部署指南【BentoML】

在本文中,我们将完成 BentoML 和 Diffusers 库之间的集成过程。 通过使用 Stable Diffusion 2.0 作为案例研究,你可以了解如何构建和部署生产就绪的 Stable Diffusion 服务。 推荐:用 NSDT编辑器 快速搭建可编程3D场景 Stable Diffusion 2.0 …

“五度情报站”微信小程序上线,让情报信息唾手可得!

当下,全球经济迅速发展,企业的市场竞争环境日益激烈,面对这样的严峻形势,情报信息的获取、分析和应用对于企业的发展变得至关重要。‘五度易链’作为中国产业大数据服务先锋,围绕企业对于情报信息的多元化需求&#xf…

elasticsearch(ES)分布式搜索引擎04——(数据聚合,自动补全,数据同步,ES集群)

目录 1.数据聚合1.1.聚合的种类1.2.DSL实现聚合1.2.1.Bucket聚合语法1.2.2.聚合结果排序1.2.3.限定聚合范围1.2.4.Metric聚合语法1.2.5.小结 1.3.RestAPI实现聚合1.3.1.API语法1.3.2.业务需求1.3.3.业务实现 2.自动补全2.1.拼音分词器2.2.自定义分词器2.3.自动补全查询2.4.实现…

进阶JAVA篇-StringBuilder类与StringBuffer类的常用API(二)

目录 API 1.0 StringBuilder 类概念 1.1StringBuilder 类中构造器 1.2 StringBuilder 类中 append()方法 1.3 StringBuilder 类中 reverse() 方法 1.4 StringBuilder 类中 length() 方法 1.5 StringBuilder 类中 toString() 方法 1.6 为什么操作字符串…

微信小程序--下拉选择框组件封装,可CV直接使用

一、起因 接到的项目需求,查看ui设计图后,由于微信小程序官方设计的下拉选择框不符合需求,而且常用的第三方库也没有封装类似的,所以选择自己自定义组件。在此记录一下,方便日后复用。 ui设计图如下: 微信官方提供的选择框 对比发现并不能实现我们想要的功能。 二、自定义组件…