深度学习模型keras第二十三讲:在KerasCV中使用SAM进行任何图像分割

1 SAM概念

###1.1 SAM定义

Segment Anything Model(SAM)是一种基于深度学习的图像分割模型,其主要特点包括:

  • 高质量的图像分割:SAM可以从输入提示(如点、框、文字等)生成高质量的对象掩模,实现对图像中对象的精确分割。
  • 零次学习性能:SAM已经在一个包含1100万张图像和110亿个掩模的数据集上进行了训练,具有强大的零次学习性能。这意味着它可以迁移到新的图像分布和任务中,即使在训练阶段没有见过的物体类别也能够进行分割。
  • 网络结构:SAM采用了类似于U-Net的编码器-解码器结构。编码器部分由多个卷积层和池化层组成,用于提取图像特征;解码器部分则由多个反卷积层和上采样层组成,用于将特征图恢复到原始图像大小,并生成分割结果。
  • 通用性:SAM足够通用,可以涵盖广泛的用例,具有强大的零样本迁移能力。它已经学会了关于物体的一般概念,可以为任何图像或视频中的任何物体生成掩码,甚至包括在训练过程中没有遇到过的物体和图像类型。
  • 交互性和灵活性:SAM采用了可提示的方法,可以根据不同的数据进行训练,并且可以适应特定的任务。它支持灵活的提示,需要分摊实时计算掩码以允许交互使用,并且必须具有模糊性意识。
  • 强大的泛化性:SAM在边缘检测、物体检测、显著物体识别、工业异常检测等下游任务上表现出很强的泛化性。

总的来说,Segment Anything Model(SAM)是一种强大且灵活的图像分割模型,可以在广泛的应用场景中实现高质量的图像分割。它的出现将大大推动计算机视觉领域的发展,为自动驾驶、医学图像分析、卫星遥感图像分析等领域提供更准确、更高效的解决方案。

1.2 SAM的kerasCV实现

Segment Anything Model(SAM)通过输入如点或框等提示,产生高质量的对象掩码,并且它可以用于生成图像中所有对象的掩码。该模型在包含1100万张图像和110亿个掩码的数据集上进行了训练,并在各种分割任务上表现出强大的零次学习性能。

在本指南中,我们将展示如何使用KerasCV实现Segment Anything Model,并展示TensorFlow和JAX在性能提升方面的强大功能。

首先,让我们为我们的演示获取所有依赖项和图像。

!pip install -Uq keras-cv
!pip install -Uq keras
!wget -q https://raw.githubusercontent.com/facebookresearch/segment-anything/main/notebooks/images/truck.jpg

1.3 使用准备

import os

os.environ["KERAS_BACKEND"] = "jax"

import timeit
import numpy as np
import matplotlib.pyplot as plt
import keras
from keras import ops
import keras_cv

2 使用SAM

2.1定义辅助函数

让我们定义一些辅助函数,用于可视化图像、提示以及分割结果。

def show_mask(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])
    h, w = mask.shape[-2:]
    mask_image = mask.reshape(h, w, 1) * color.reshape(1, 1, -1)
    ax.imshow(mask_image)


def show_points(coords, labels, ax, marker_size=375):
    pos_points = coords[labels == 1]
    neg_points = coords[labels == 0]
    ax.scatter(
        pos_points[:, 0],
        pos_points[:, 1],
        color="green",
        marker="*",
        s=marker_size,
        edgecolor="white",
        linewidth=1.25,
    )
    ax.scatter(
        neg_points[:, 0],
        neg_points[:, 1],
        color="red",
        marker="*",
        s=marker_size,
        edgecolor="white",
        linewidth=1.25,
    )


def show_box(box, ax):
    box = box.reshape(-1)
    x0, y0 = box[0], box[1]
    w, h = box[2] - box[0], box[3] - box[1]
    ax.add_patch(
        plt.Rectangle((x0, y0), w, h, edgecolor="green", facecolor=(0, 0, 0, 0), lw=2)
    )


def inference_resizing(image, pad=True):
    # Compute Preprocess Shape
    image = ops.cast(image, dtype="float32")
    old_h, old_w = image.shape[0], image.shape[1]
    scale = 1024 * 1.0 / max(old_h, old_w)
    new_h = old_h * scale
    new_w = old_w * scale
    preprocess_shape = int(new_h + 0.5), int(new_w + 0.5)

    # Resize the image
    image = ops.image.resize(image[None, ...], preprocess_shape)[0]

    # Pad the shorter side
    if pad:
        pixel_mean = ops.array([123.675, 116.28, 103.53])
        pixel_std = ops.array([58.395, 57.12, 57.375])
        image = (image - pixel_mean) / pixel_std
        h, w = image.shape[0], image.shape[1]
        pad_h = 1024 - h
        pad_w = 1024 - w
        image = ops.pad(image, [(0, pad_h), (0, pad_w), (0, 0)])
        # KerasCV now rescales the images and normalizes them.
        # Just unnormalize such that when KerasCV normalizes them
        # again, the padded values map to 0.
        image = image * pixel_std + pixel_mean
    return image

2.2获取预训练的SAM模型

我们可以使用KerasCV的from_preset工厂方法来初始化一个训练好的SAM模型。在这里,我们使用在SA-1B数据集上训练的大型ViT主干网络(sam_huge_sa1b)来获取高质量的分割掩码。程序员也可以选择使用sam_large_sa1bsam_base_sa1b以获取更好的性能(但可能会降低分割掩码的质量)。

model = keras_cv.models.SegmentAnythingModel.from_preset("sam_huge_sa1b")

2.3理解提示

Segment Anything 允许使用点、框和掩码对图像进行提示:

点提示是所有提示中最基本的:模型尝试根据图像上的一个点来猜测对象。这个点可以是前景点(即所需的分割掩码中包含该点)或背景点(即该点位于所需掩码之外)。

另一种提示模型的方式是使用框。给定一个边界框,模型尝试分割其中包含的对象。

最后,模型也可以使用掩码本身进行提示。例如,这可以用于细化先前预测或已知的分割掩码的边界。

使该模型极其强大的是能够组合上述提示。点、框和掩码提示可以以多种方式组合,以获得最佳结果。通过组合不同的提示,用户可以更准确地指定他们想要分割的对象,从而优化模型的输出。

在KerasCV中将这些提示传递给Segment Anything模型时的语义。SAM模型的输入是一个字典,其键包括:

"images": 要分割的图像批次。必须具有形状 (B, 1024, 1024, 3),其中B是批次大小。

"points": 点提示的批次。每个点都是图像左上角开始的(x, y)坐标。换句话说,每个点都是形式为(r, c)的,其中r和c是图像中像素的行和列。必须具有形状 (B, N, 2),其中N是每个图像中点的数量。

"labels": 给定点的标签批次。1代表前景点,0代表背景点。必须具有形状 (B, N),与点提示相对应。

"boxes": 框的批次。请注意,模型每次仅接受一个框。因此,预期的形状是 (B, 1, 2, 2)。每个框都是两个点的集合:框的左上角和右下角。这里的点遵循与点提示相同的语义。这里的第二个维度中的1表示存在框提示。如果缺少框提示,则必须传递形状为 (B, 0, 2, 2) 的占位符输入。

"masks": 掩码的批次。与框提示一样,每个图像只允许一个掩码提示。如果存在掩码提示,则输入掩码的形状必须为 (B, 1, 256, 256, 1);如果缺少掩码提示,则形状为 (B, 0, 256, 256, 1)。

占位符提示仅在直接调用模型(即 model(...))时需要。当调用 predict 方法时,可以从输入字典中省略缺失的提示。这允许模型在缺少某些提示时仍然运行,并仅根据提供的提示进行预测。

2.3.1点提示

首先,让我们使用点提示对图像进行分割。我们加载图像并将其调整为预训练的SAM模型期望的图像大小(1024, 1024)。

# Load our image
image = np.array(keras.utils.load_img("truck.jpg"))
image = inference_resizing(image)

plt.figure(figsize=(10, 10))
plt.imshow(ops.convert_to_numpy(image) / 255.0)
plt.axis("on")
plt.show()

在这里插入图片描述
接下来,我们将定义我们想要分割的对象上的点。让我们尝试在坐标 (284, 213) 处分割卡车的窗户。

为了做到这一点,我们需要准备输入到Segment Anything模型的数据,包括图像、点提示以及点的标签(如果模型需要)。

# Define the input point prompt
input_point = np.array([[284, 213.5]])
input_label = np.array([1])

plt.figure(figsize=(10, 10))
plt.imshow(ops.convert_to_numpy(image) / 255.0)
show_points(input_point, input_label, plt.gca())
plt.axis("on")
plt.show()

在这里插入图片描述
现在让我们调用模型的predict方法来获取分割掩码。

注意:我们不直接调用模型(即model(…)),因为这样做需要占位符提示。predict方法会自动处理缺失的提示,所以我们选择调用它。另外,如果没有提供框提示,点提示和标签需要分别用零点提示和-1标签提示来填充。下面的代码块演示了这是如何工作的。

outputs = model.predict(
    {
        "images": image[np.newaxis, ...],
        "points": np.concatenate(
            [input_point[np.newaxis, ...], np.zeros((1, 1, 2))], axis=1
        ),
        "labels": np.concatenate(
            [input_label[np.newaxis, ...], np.full((1, 1), fill_value=-1)], axis=1
        ),
    }
)

SegmentAnythingModel.predict 方法返回两个输出。首先是 logits(分割掩码),形状为 (1, 4, 256, 256),另一个是每个预测掩码的 IoU 置信度分数(形状为 (1, 4))。预训练的 SAM 模型会预测四个掩码:第一个是模型根据给定的提示能够产生的最佳掩码,而其他三个是备用掩码,可以在最佳预测不包含所需对象的情况下使用。用户可以选择他们喜欢的任何掩码。

以下代码实现可视化模型返回的掩码。

# Resize the mask to our image shape i.e. (1024, 1024)
mask = inference_resizing(outputs["masks"][0][0][..., None], pad=False)[..., 0]
# Convert the logits to a numpy array
# and convert the logits to a boolean mask
mask = ops.convert_to_numpy(mask) > 0.0
iou_score = ops.convert_to_numpy(outputs["iou_pred"][0][0])

plt.figure(figsize=(10, 10))
plt.imshow(ops.convert_to_numpy(image) / 255.0)
show_mask(mask, plt.gca())
show_points(input_point, input_label, plt.gca())
plt.title(f"IoU Score: {iou_score:.3f}", fontsize=18)
plt.axis("off")
plt.show()

在这里插入图片描述
正如预期的那样,模型返回了卡车车窗的一个分割掩码。但是,我们的点提示也可能意味着一系列其他的东西。例如,另一个可能包含我们点的掩码只是车窗的右侧或整个卡车。

让我们也可视化模型预测的其他掩码。

fig, ax = plt.subplots(1, 3, figsize=(20, 60))
masks, scores = outputs["masks"][0][1:], outputs["iou_pred"][0][1:]
for i, (mask, score) in enumerate(zip(masks, scores)):
    mask = inference_resizing(mask[..., None], pad=False)[..., 0]
    mask, score = map(ops.convert_to_numpy, (mask, score))
    mask = 1 * (mask > 0.0)
    ax[i].imshow(ops.convert_to_numpy(image) / 255.0)
    show_mask(mask, ax[i])
    show_points(input_point, input_label, ax[i])
    ax[i].set_title(f"Mask {i+1}, Score: {score:.3f}", fontsize=12)
    ax[i].axis("off")
plt.show()

在这里插入图片描述

2.3.2边界框提示

现在,让我们看看如何使用边界框来提示模型。边界框由两个点指定,即边界框的左上角和右下角的坐标,以xyxy格式表示。让我们使用卡车左前轮胎周围的边界框来提示模型。

# Let's specify the box
input_box = np.array([[240, 340], [400, 500]])

outputs = model.predict(
    {"images": image[np.newaxis, ...], "boxes": input_box[np.newaxis, np.newaxis, ...]}
)
mask = inference_resizing(outputs["masks"][0][0][..., None], pad=False)[..., 0]
mask = ops.convert_to_numpy(mask) > 0.0

plt.figure(figsize=(10, 10))
plt.imshow(ops.convert_to_numpy(image) / 255.0)
show_mask(mask, plt.gca())
show_box(input_box, plt.gca())
plt.axis("off")
plt.show()

在这里插入图片描述

2.3.3组合提示

为了发挥模型的真正潜力,让我们将边界框和点提示结合起来,看看模型会如何表现。

# Let's specify the box
input_box = np.array([[240, 340], [400, 500]])
# Let's specify the point and mark it background
input_point = np.array([[325, 425]])
input_label = np.array([0])

outputs = model.predict(
    {
        "images": image[np.newaxis, ...],
        "points": input_point[np.newaxis, ...],
        "labels": input_label[np.newaxis, ...],
        "boxes": input_box[np.newaxis, np.newaxis, ...],
    }
)
mask = inference_resizing(outputs["masks"][0][0][..., None], pad=False)[..., 0]
mask = ops.convert_to_numpy(mask) > 0.0

plt.figure(figsize=(10, 10))
plt.imshow(ops.convert_to_numpy(image) / 255.0)
show_mask(mask, plt.gca())
show_box(input_box, plt.gca())
show_points(input_point, input_label, plt.gca())
plt.axis("off")
plt.show()

在这里插入图片描述

2.3.4文本提示

最后,让我们看看如何与 KerasCV 的 SegmentAnythingModel 一起使用文本提示。

对于这个演示,我们将使用官方的 Grounding DINO 模型。Grounding DINO 是一个模型,它接受(图像,文本)对作为输入,并在图像中生成由文本描述的对象周围的边界框。你可以参考相关的论文以获取更多关于模型实现的详细信息。

对于演示的这一部分,我们需要从源代码安装 groundingdino 包:

首先,你需要克隆 groundingdino 的仓库,然后按照其官方文档中的说明进行安装。这通常涉及安装依赖项,并在克隆的目录中运行适当的安装命令(可能是 pip install .setup.py 脚本)。

请注意,由于 groundingdino 是一个独立的项目,并不直接包含在 KerasCV 中,所以你需要按照 groundingdino 的指南来安装它。

一旦你安装了 groundingdino,你就可以结合使用 KerasCV 的 SegmentAnythingModel 和 groundingdino 生成的边界框来进一步细化或验证你的分割结果。例如,你可以使用 groundingdino 生成的边界框作为点或边界框提示,然后让 SegmentAnythingModel 在该区域内进行更精细的分割。

准备groundingdino

pip install -U git+https://github.com/IDEA-Research/GroundingDINO.git
!wget -q https://github.com/IDEA-Research/GroundingDINO/releases/download/v0.1.0-alpha/groundingdino_swint_ogc.pth
!wget -q https://raw.githubusercontent.com/IDEA-Research/GroundingDINO/v0.1.0-alpha2/groundingdino/config/GroundingDINO_SwinT_OGC.py
from groundingdino.util.inference import Model as GroundingDINO

CONFIG_PATH = "GroundingDINO_SwinT_OGC.py"
WEIGHTS_PATH = "groundingdino_swint_ogc.pth"

grounding_dino = GroundingDINO(CONFIG_PATH, WEIGHTS_PATH)

加载照片

filepath = keras.utils.get_file(
    origin="https://storage.googleapis.com/keras-cv/test-images/mountain-dog.jpeg"
)
image = np.array(keras.utils.load_img(filepath))
image = ops.convert_to_numpy(inference_resizing(image))

plt.figure(figsize=(10, 10))
plt.imshow(image / 255.0)
plt.axis("on")
plt.show()

在这里插入图片描述
我们首先使用 Grounding DINO 模型预测我们想要分割的对象的边界框。然后,我们使用这个边界框来提示 SAM 模型,以获得分割掩码。

让我们尝试分割出狗的项圈。改变下面的图像和文本,以使用你的图像中的文本来分割任何你想要的东西!

# Let's predict the bounding box for the harness of the dog
boxes = grounding_dino.predict_with_caption(image.astype(np.uint8), "harness")
boxes = np.array(boxes[0].xyxy)

outputs = model.predict(
    {
        "images": np.repeat(image[np.newaxis, ...], boxes.shape[0], axis=0),
        "boxes": boxes.reshape(-1, 1, 2, 2),
    },
    batch_size=1,
)

就是这样!我们结合使用 Grounding DINO + SAM,根据文本提示得到了一个分割掩码!这是一种非常强大的技术,可以组合不同的模型来扩展应用!

然后可视化结果。

plt.figure(figsize=(10, 10))
plt.imshow(image / 255.0)

for mask in outputs["masks"]:
    mask = inference_resizing(mask[0][..., None], pad=False)[..., 0]
    mask = ops.convert_to_numpy(mask) > 0.0
    show_mask(mask, plt.gca())
    show_box(boxes, plt.gca())

plt.axis("off")
plt.show()

在这里插入图片描述

2.4优化SAM

你可以使用 mixed_float16bfloat16 数据类型策略来在相对较低精度损失的情况下,获得巨大的速度提升和内存优化。

# Load our image
image = np.array(keras.utils.load_img("truck.jpg"))
image = inference_resizing(image)

# Specify the prompt
input_box = np.array([[240, 340], [400, 500]])

# Let's first see how fast the model is with float32 dtype
time_taken = timeit.repeat(
    'model.predict({"images": image[np.newaxis, ...], "boxes": input_box[np.newaxis, np.newaxis, ...]}, verbose=False)',
    repeat=3,
    number=3,
    globals=globals(),
)
print(f"Time taken with float32 dtype: {min(time_taken) / 3:.10f}s")

# Set the dtype policy in Keras
keras.mixed_precision.set_global_policy("mixed_float16")

model = keras_cv.models.SegmentAnythingModel.from_preset("sam_huge_sa1b")

time_taken = timeit.repeat(
    'model.predict({"images": image[np.newaxis, ...], "boxes": input_box[np.newaxis, np.newaxis, ...]}, verbose=False)',
    repeat=3,
    number=3,
    globals=globals(),
)
print(f"Time taken with float16 dtype: {min(time_taken) / 3:.10f}s")

3 总结

前面的讨论主要涵盖了如何使用不同的提示方法(包括点、边界框和文本)来引导图像分割模型(如SegmentAnythingModel,简称SAM)进行更精确的分割。此外,还提到了如何通过结合不同的模型(如Grounding DINO与SAM)来扩展图像分割应用的可能性。最后,讨论了如何通过使用mixed_float16bfloat16数据类型策略来优化SAM,以在几乎不损失精度的同时实现速度和内存的显著提升。

  • 多种提示方法:通过使用点、边界框和文本等不同的提示方法,可以有效地引导SAM模型进行更准确的图像分割。

  • 模型组合:通过将Grounding DINO等模型与SAM结合使用,可以扩展图像分割应用的范围,提高分割的准确性和效率。

  • 优化策略:使用mixed_float16bfloat16数据类型策略对SAM进行优化,可以在保持模型性能的同时,显著提升模型的运行速度和内存使用效率。这对于处理大规模数据集或在资源受限的环境下运行模型尤为重要。

这些讨论不仅展示了图像分割技术的多样性和灵活性,还强调了在实际应用中优化模型性能的重要性。通过结合不同的模型和优化策略,我们可以开发出更加高效、准确的图像分割解决方案,满足各种应用场景的需求。

KerasCV 的 SegmentAnythingModel 支持多种应用,并借助 Keras 3 能够在 TensorFlow、JAX 和 PyTorch 上运行该模型!借助 JAX 和 TensorFlow 中的 XLA 加速,该模型的运行速度比原始实现快数倍。此外,通过 Keras 的混合精度支持,只需一行代码即可优化内存使用和计算时间!

对于更高级的用法,请查看自动掩码生成器(Automatic Mask Generator)的演示。这个演示展示了如何利用 SegmentAnythingModel 和其他技术来自动生成高质量的图像分割掩码,从而进一步扩展图像分割的应用领域。无论是进行对象检测、图像分析还是其他复杂的视觉任务,自动掩码生成器都能提供强大的支持,帮助开发者更高效地实现他们的目标。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Hive SQL 每日一题】行列转换

文章目录 行转列列传行 行转列 测试数据: DROP TABLE IF EXISTS student_scores;CREATE TABLE student_scores (student_id INT,subject STRING,score INT );INSERT INTO student_scores (student_id, subject, score) VALUES (1, Math, 85), (1, English, 78), (…

高效爬取Reddit:C#与RestSharp的完美结合

介绍 在数据驱动的时代,网络爬虫已经成为获取网页数据的重要工具。Reddit,作为全球最大的社区平台之一,以其丰富的用户生成内容、广泛的讨论话题和实时的信息更新吸引了大量用户。对于研究人员和开发者而言,Reddit提供了宝贵的数…

VMware Workstation 虚拟机安装 ubuntu 24.04 server 详细教程 服务器安装图形化界面

1 阿里云下载 ubuntu-releases安装包下载_开源镜像站-阿里云 2 打开vmware,新建虚拟机 3 选择下载的镜像,开始安装 3 光驱这里修改下 4 重新启动,安装图形化界面 #更新软件包列表 sudo apt-get update #安装Ubuntu图形桌面 sudo apt install ubuntu-desktop 5 安…

南京沁恒微USB HUB CH334/CH335多种封装规格选择,外围简单,价格还美丽

概述: CH334 和 CH335 是符合 USB2.0 协议规范的 全速,下行端口支持 USB2.0 高速 480Mbps 个 TT 分时调度 4 个下行端口),还支持高性能的 工业级设计,外围精简,可应用于计算机和工控机主板 特点&#xff1…

单细胞分析(Signac): PBMC scATAC-seq 整合

引言 在本教学指南中,我们将探讨由10x Genomics公司提供的人类外周血单核细胞(PBMCs)的单细胞ATAC-seq数据集。 加载包 首先加载 Signac、Seurat 和我们将用于分析人类数据的其他一些包。 if (!requireNamespace("EnsDb.Hsapiens.v75&qu…

数据源管理|JDBC|JdbcTemplate|MybatisPlusGenerator

个人博客:无奈何杨(wnhyang) 个人语雀:wnhyang 共享语雀:在线知识共享 Github:wnhyang - Overview 复杂的项目常常会涉及到多数据源的配置,解决方案也是有很多。但这篇文章不是讲这个的&…

el-table 实现嵌套表格的思路及完整功能代码

要实现的需求是这样的: 本来我是用 el-table 的 :span-method 方法实现的,但发现合并起来有问题,跟我的需求差距有些大,于是我想到了嵌套表格。但是嵌套完之后的样子也是很奇怪: 不要气馁,思路还是对的&a…

MacOS使用PhpStorm+Xdebug断点调式

基本环境: MacOS m1 PhpStorm 2024.1 PHP7.4.33 Xdebug v3.1.6 1、php.ini 配置 [xdebug] zend_extension "/opt/homebrew/Cellar/php7.4/7.4.33_6/pecl/20190902/xdebug.so" xdebug.idekey "PHPSTORM" xdebug.c…

SpringBoot集成Logback将日志写入文件夹

一、logback简介: 目前比较常用的ava日志框架:Logback、log4j、log4j2、JUL等等。 Logback是在log4j的基础上重新开发的一套日志框架,是完全实现SLF4J接口API(也叫日志门面)。 Logback 的架构非常通用,可以应用于不同的环境。目前logback分为…

【人工智能项目】小车障碍物识别与模型训练(完整工程资料源码)

实物演示效果: 一、绪论: 1.1 设计背景 小车障碍物识别与模型训练的设计背景通常涉及以下几个方面: 随着自动驾驶技术的发展,小车(如无人驾驶汽车、机器人等)需要能够在复杂的环境中自主导航。障碍物识别是实现这一目标的关键技术之一,它允许小车检测并避开路上的障碍物…

C++-函数

函数(Function):是一个提前封装好的、可重复使用的、完成特定功能的独立代码单元。 特点:提前封装、可重复使用的、完成特定功能 将针对特定功能的、有重复使用需求的代码,提前封装到函数内, 在需要的时候…

IEN在Web3.0中的性能与安全优势

随着Web3.0的快速发展,优化网络基础设施变得至关重要。智能生态网络(Intelligent Ecological Network, IEN)作为新一代网络架构,在提升性能与增强安全方面展现出巨大潜力。本文将深入探讨IEN在Web3.0中的技术优势,并展…

Qt输入输出类使用总结

Qt输入输出类简介 QTextStream 类(文本流)和 QDataStream 类(数据流)Qt 输入输出的两个核心类,其作用分别如下: QTextStream 类:用于对数据进行文本格式的读/写操作,可在 QString、QIODevice或 QByteArray 上运行,比如把数据输出到 QString、QIODevice 或 QByteArray 对象…

JS、Go、Rust 错误处理的不同 - JS 可以不用 Try/Catch 吗?

原文:Mateusz Piorowski - 2023.07.24 先来了解一下我的背景吧。我是一名软件开发人员,有大约十年的工作经验,最初使用 PHP,后来逐渐转向 JavaScript。 大约五年前,我开始使用 TypeScript,从那时起&#…

Go微服务——go-micro v4安装使用

安装go-micro 打开cmd窗口,执行以下命令 go install github.com/go-micro/cli/cmd/go-microlatest测试是否成功安装 go-micro -v创建服务 go-micro new service helloworldwindows 安装make 安装地址 https://gnuwin32.sourceforge.net/packages/make.htm 配置…

python从0开始学习(九)

前言 上一篇文章我们介绍了python中的序列类型和元组类型,本篇文章将接着往下将。 1、字典类型 字典类型是根据一个信息查找另一个信息的方式所构成的“键值对”,它表示索引用的键和对应的值构成的成对关系。它是一个可变数据类型,也就是说它…

JAVA基础知识100题练习、蓝桥杯竞赛题,编程基础必练题!

各位编程小伙伴们,这里可是作者花费了无数个日日夜夜,熬秃了不知道多少根头发,凭借着那超级无敌多年的编程经验,拼死拼活、千辛万苦总结出来的呀!这可是各种开发语言都绝对必须要练的基础编程知识哇!什么九…

jenkins自动化部署详解

一、准备相关软件 整个自动化部署的过程就是从git仓库拉取最新代码,然后使用maven进行构建代码,构建包构建好了之后,通过ssh发送到发布服务的linux服务器的目录,最后在此服务器上执行相关的linux命令进行发布。 此篇文章jenkins…

Linux gurb2简介

文章目录 前言一、GRUB 2简介二、GRUB 2相关文件/文件夹2.1 /etc/default/grub文件2.2 /etc/grub.d/文件夹2.3 /boot/grub/grub.cfg文件 三、grubx64.efi参考资料 前言 简单来说,引导加载程序(boot loader)是计算机启动时运行的第一个软件程…

262 基于matlab的一级倒立摆仿真

基于matlab的一级倒立摆仿真,在对一级倒立摆进行数学建模的基础上,对模型进行线性化,得到其状态空间模型,利用二次型最优控制方法得出控制率。输出角度和位置优化曲线。程序已调通,可直接运行。 262 一级倒立摆仿真 状…