【pytorch】Pytorch 中的 grid 与 各种变换
Pytorch 中的 grid 与 各种变换
数学原理
**单应性(Homography) : 也就是透视变换。**单应性最初用来研究欧几里得几何中的透视和投影,而单应性一词,从词源学上来说,大致意思是“相似的绘图”。单应性的概念被引入来理解、解释和研究视觉透视,特别是从不同角度观察两个平面物体的外观差异。
Affine
Perspective
透视变换将二维图像坐标转换为三维齐次坐标,然后应用透视变换矩阵,最后将结果转换回二维坐标。通过旋转和平移将世界坐标中的点转换为相机坐标中的坐标,然后将这些坐标投影到传感器平面上。
其中 f 是焦距,(lx, ly) 是像素的物理尺寸,(cx, cy) 是相机的光学中心,以像素为单位。
方程 (1) 明确显示了针孔相机模型如何将 3D 点 (X, Y, Z) 投影到图像坐标 (u, v)
这里假设所有点**(X, Y, Z)**所在的scene是一个平面。也就是符合公式Z = αX + βY + γ。带入可得
将 P 的项与方程 (2) 中的 α、β 和 γ 混合,得到一个新的 3 x 3 未知矩阵 M,即透视变换矩阵:
为了求解 M 的项,我们必须首先将 λ=m20 X + m21 Y +m22 代入方程 (3),得到有 9 个未知数的齐次线性方程:
求解透视变换矩阵 M 的九个条目(最多一个缩放因子),以及物平面坐标 (X, Y) 与其像素值 (u, v) 之间的四个对应关系。
9个未知数,zero space为1维。因此有一个自由度,通常被设置为1。
Pytorch 官方文档解读
grid in pytorch
基础知识
grid in Pytorch
https://pytorch.org/docs/stable/generated/torch.nn.functional.grid_sample.html
grid in numpy
图像增强中的 变换api
torchvision.transforms.functional
torchvision.transforms.functional.affine(img: Tensor, angle: float, translate: List[int], scale: float, shear: List[float], interpolation: InterpolationMode = InterpolationMode.NEAREST, fill: Optional[List[float]] = None, center: Optional[List[int]] = None)
对比关系
torchvision.transforms.functional 中的 affine,通常用于图像处理和数据增强。
torch.nn.functional 中的 affine_grid 和 grid_sample 库,通常用于深度学习模型的操作和图像变换。torch.nn.functional.affine_grid 函数用于生成仿射变换的网格,torch.nn.functional.grid_sample 函数用于在输入图像上应用仿射变换。这些函数通常用于构建自定义的图像变换层或模型,以实现更灵活的图像空间变换。
另外图像变换中有perspective,而nn中没有。
torchvision.transforms.functional.perspective(img: Tensor, startpoints: List[List[int]], endpoints: List[List[int]], interpolation: InterpolationMode = InterpolationMode.BILINEAR, fill: Optional[List[float]] = None) → Tensor
img(Tensor):输入的图像,通常是一个PyTorch张量,可以是单通道或多通道的图像。startpoints(List[List[int]]):一个包含4个起始点坐标的列表,每个起始点用一个[x, y]列表表示。这些起始点用于指定透视变换的原始四边形的四个顶点。endpoints(List[List[int]]):一个包含4个目标点坐标的列表,每个目标点用一个[x, y]列表表示。这些目标点用于指定透视变换后的四边形的四个顶点。interpolation(InterpolationMode,可选):指定插值方法的枚举类型。它表示在透视变换期间如何对图像进行插值。可选的插值方法包括InterpolationMode.NEAREST(最近邻插值)和InterpolationMode.BILINEAR(双线性插值)等。fill(Optional[List[float]],可选):一个包含用于填充图像的颜色值的列表,通常表示为[R, G, B]。如果未提供此参数,则使用默认值[0, 0, 0]进行填充。startpoints和endpoints分别指定了原始四边形和目标四边形的四个顶点,通过这些顶点之间的映射关系,函数将原始图像进行透视变换。interpolation参数允许你选择插值方法以保持图像的质量。如果需要在深度学习中执行透视变换,这个函数可以用于构建自定义的图像增强层。
具体实现:
函数用于执行透视变换,它接受输入图像、原始四边形的四个顶点、变换后的四边形的四个顶点、插值方式和填充值作为参数。函数根据参数选择使用Pillow(F_pil.perspective)或PyTorch(F_t.perspective)来执行透视变换。如果输入是PIL图像,它将使用Pillow进行变换,如果输入是PyTorch张量,它将使用PyTorch进行变换。函数的返回值是变换后的图像。
def perspective(img: Tensor,startpoints: List[List[int]],endpoints: List[List[int]],interpolation: InterpolationMode = InterpolationMode.BILINEAR,fill: Optional[List[float]] = None,
) -> Tensor:"""执行给定图像的透视变换。如果图像是 Torch 张量,则预期其具有 [..., H, W] 的形状,其中 ... 表示任意数量的前导维度。Args:img (PIL 图像或张量): 要进行变换的图像。startpoints (list of list of ints): 包含四个包含两个整数的列表的列表,对应于原始图像的四个角``[左上角, 右上角, 右下角, 左下角]``。endpoints (list of list of ints): 包含四个包含两个整数的列表的列表,对应于变换后图像的四个角``[左上角, 右上角, 右下角, 左下角]``。interpolation (InterpolationMode): 期望的插值方式枚举,由:class:`torchvision.transforms.InterpolationMode` 定义。默认为 ``InterpolationMode.BILINEAR``。如果输入为张量,则仅支持 ``InterpolationMode.NEAREST`` 和 ``InterpolationMode.BILINEAR``。也可以接受对应的Pillow整数常数,如 ``PIL.Image.BILINEAR``。fill (sequence 或数字,可选): 用于填充变换后图像之外区域的像素值。如果给定一个数字,则分别用于所有波段。.. 注意::在 TorchScript 模式下,不支持单个 int/float 值,请使用长度为 1 的序列:``[value, ]``。Returns:PIL 图像或张量: 变换后的图像。"""# 检查是否处于 TorchScript 或 Tracing 模式下,如果不是,则记录 API 使用情况if not torch.jit.is_scripting() and not torch.jit.is_tracing():_log_api_usage_once(perspective)# 获取透视变换的系数,这些系数将在后续的变换中使用coeffs = _get_perspective_coeffs(startpoints, endpoints)# 如果 interpolation 是整数,将其转换为对应的 InterpolationModeif isinstance(interpolation, int):interpolation = _interpolation_modes_from_int(interpolation)elif not isinstance(interpolation, InterpolationMode):raise TypeError("Argument interpolation should be a InterpolationMode or a corresponding Pillow integer constant")# 如果输入不是 Torch 张量,则使用 Pillow 进行透视变换if not isinstance(img, torch.Tensor):pil_interpolation = pil_modes_mapping[interpolation]return F_pil.perspective(img, coeffs, interpolation=pil_interpolation, fill=fill)# 如果输入是 Torch 张量,则使用 Torch 进行透视变换return F_t.perspective(img, coeffs, interpolation=interpolation.value, fill=fill)
利用**_get_perspective_coeffs** 利用最小二乘法获取变换矩阵。
**
def** **_get_perspective_coeffs(startpoints:** **List[List[**int**]],** **endpoints:** **List[List[**int**]])** **->** **List[**float**]:**
用于计算透视变换的系数,这些系数会在透视变换时使用。函数根据给定的起始点(原始图像的四个角)和目标点(变换后图像的四个角)来计算这些系数,然后将它们返回供透视变换使用。函数内部使用了一些线性代数和矩阵运算,最终返回一个包含8个系数的列表,这些系数可以用于对图像进行透视变换。
def _get_perspective_coeffs(startpoints: List[List[int]], endpoints: List[List[int]]) -> List[float]:"""Helper function to get the coefficients (a, b, c, d, e, f, g, h) for the perspective transforms.In Perspective Transform each pixel (x, y) in the original image gets transformed as,(x, y) -> ( (ax + by + c) / (gx + hy + 1), (dx + ey + f) / (gx + hy + 1) )Args:startpoints (list of list of ints): List containing four lists of two integers corresponding to four corners``[top-left, top-right, bottom-right, bottom-left]`` of the original image.endpoints (list of list of ints): List containing four lists of two integers corresponding to four corners``[top-left, top-right, bottom-right, bottom-left]`` of the transformed image.Returns:octuple (a, b, c, d, e, f, g, h) for transforming each pixel."""# 创建一个8x8的零矩阵 a_matrix,用于存储变换的系数a_matrix = torch.zeros(2 * len(startpoints), 8, dtype=torch.float)# 使用循环迭代四个角的坐标,计算变换系数并填充 a_matrixfor i, (p1, p2) in enumerate(zip(endpoints, startpoints)):# 填充 a_matrix 的每一行a_matrix[2 * i, :] = torch.tensor([p1[0], p1[1], 1, 0, 0, 0, -p2[0] * p1[0], -p2[0] * p1[1]])a_matrix[2 * i + 1, :] = torch.tensor([0, 0, 0, p1[0], p1[1], 1, -p2[1] * p1[0], -p2[1] * p1[1]])# 创建 b_matrix,用于存储起始点坐标的矩阵并将其展平b_matrix = torch.tensor(startpoints, dtype=torch.float).view(8)# 使用最小二乘法计算变换系数 resres = torch.linalg.lstsq(a_matrix, b_matrix, driver="gels").solution# 将结果转换为列表并返回output: List[float] = res.tolist()return output
Pytorch 手写代码
perspective
# PyTorch 实现代码
import torch
import torch.nn.functional as Fdef custom_perspective_transform(image, perspective_matrix):n, c, h, w = image.shapedevice = image.device# 创建二维坐标网格grid_x, grid_y = torch.meshgrid(torch.linspace(-1, 1, w, device=device),torch.linspace(-1, 1, h, device=device))ones = torch.ones_like(grid_x)# 转换为齐次坐标grid_homogeneous = torch.stack([grid_x, grid_y, ones], dim=0).reshape(3, -1) # [3, H*W]# 应用透视变换矩阵grid_transformed = torch.mm(perspective_matrix, grid_homogeneous) # [3, H*W]# 将齐次坐标转换回普通坐标xy = (grid_transformed[:2, :] / grid_transformed[2:3, :]).t().reshape(h, w, 2)# 调整形状以适应 grid_samplexy = xy.unsqueeze(0).repeat(n, 1, 1, 1) # [N, H, W, 2]# 应用网格采样transformed_image = F.grid_sample(image, xy, align_corners=True)return transformed_image# 示例使用
# 假设 'checkerboard_tensor' 是之前创建的方格图像张量
# 'perspective_matrix' 是透视变换矩阵
transformed_checkerboard = custom_perspective_transform(checkerboard_tensor, perspective_matrix)
Perspective 可反向传播
import torch
import torch.nn.functional as F
from torch.autograd import Function
from torchvision.transforms.functional import InterpolationMode
from typing import List, Optionalclass PerspectiveTransformFunction(Function):@staticmethoddef forward(ctx, img, startpoints, endpoints, interpolation, fill):# 计算透视变换的系数coeffs = _get_perspective_coeffs(startpoints, endpoints)# 执行透视变换if not isinstance(interpolation, InterpolationMode):interpolation = InterpolationMode(interpolation)output = F.grid_sample(img, coeffs.view(1, 8, 1, 1), interpolation=interpolation, padding_mode='border', align_corners=True)# 保存需要的信息以备反向传播ctx.save_for_backward(coeffs, img)ctx.interpolation = interpolationctx.fill = fillreturn output@staticmethoddef backward(ctx, grad_output):# 获取需要的信息coeffs, img = ctx.saved_tensorsinterpolation = ctx.interpolationfill = ctx.fill# 计算梯度grad_input = F.grid_sample(grad_output, coeffs.view(1, 8, 1, 1), interpolation=interpolation, padding_mode='border', align_corners=True)return grad_input, None, None, None, Noneclass PerspectiveTransform:def __init__(self, startpoints, endpoints, interpolation=InterpolationMode.BILINEAR, fill=None):self.startpoints = startpointsself.endpoints = endpointsself.interpolation = interpolationself.fill = filldef __call__(self, img):return PerspectiveTransformFunction.apply(img, self.startpoints, self.endpoints, self.interpolation, self.fill)
使用测试案例
from torchvision.transforms.functional import to_pil_image, to_tensor
from PIL import Image# 步骤1: 生成棋盘格图像并保存到磁盘
# 创建一个函数来生成棋盘格图像
def generate_chessboard(width, height, rows, cols):image = Image.new("RGB", (width, height), (255, 255, 255))draw = ImageDraw.Draw(image)cell_width = width // colscell_height = height // rowscolor1 = (0, 0, 0)color2 = (255, 255, 255)for row in range(rows):for col in range(cols):if (row + col) % 2 == 0:color = color1else:color = color2x0 = col * cell_widthy0 = row * cell_heightx1 = x0 + cell_widthy1 = y0 + cell_heightdraw.rectangle([x0, y0, x1, y1], fill=color)image.save("chessboard.png")# 调用生成函数来生成棋盘格图像
generate_chessboard(400, 400, 8, 8)# 步骤2: 执行透视变换
# 创建一个透视变换对象
startpoints = [[0, 0], [300, 0], [300, 300], [0, 300]]
endpoints = [[50, 50], [250, 0], [250, 250], [50, 250]]
transform = PerspectiveTransform(startpoints, endpoints)# 读取生成的棋盘格图像
chessboard_img = Image.open("chessboard.png")# 将图像转换为Tensor
img_tensor = to_tensor(chessboard_img).unsqueeze(0)# 执行透视变换
transformed_img = transform(img_tensor)# 步骤3: 将变换后的图像显示或保存
output_img = to_pil_image(transformed_img.squeeze(0))
output_img.show() # 显示变换后的图像
output_img.save("transformed_chessboard.png") # 保存变换后的图像
库代码
OpenCV 文档:
Perspective
https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html#warpperspective
Affine
https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html#warpaffine
https://docs.opencv.org/4.x/d4/d61/tutorial_warp_affine.html
尝试代码
import torch
import torch.nn.functional as F
import numpy as np
import matplotlib.pyplot as pltdef perspective_transform(image, perspective_matrix):n, c, h, w = image.shape# 生成标准网格grid = F.affine_grid(torch.eye(2, 3).unsqueeze(0), image.size(), align_corners=False)# 将网格转换为齐次坐标homogeneous_grid = torch.cat([grid, torch.ones(n, h, w, 1, device=grid.device)], dim=-1)# 应用透视变换矩阵warped_grid = torch.matmul(homogeneous_grid, perspective_matrix.transpose(1, 2))# 将齐次坐标转换回非齐次坐标warped_grid_xy = warped_grid[..., :2] / warped_grid[..., 2:3]warped_grid_xy = warped_grid_xy.permute(0, 3, 1, 2) # 转换为 (N, C, H, W) 格式# 应用网格采样transformed_image = F.grid_sample(image, warped_grid_xy, align_corners=False, padding_mode='zeros')return transformed_image# 创建一个简单的方格图像
def create_checkerboard(h, w, square_size):img = np.zeros((h, w))s = square_sizefor y in range(0, h, s*2):for x in range(0, w, s*2):img[y:y+s, x:x+s] = 1.0img[y+s:y+s*2, x+s:x+s*2] = 1.0return img# 创建方格图像
h, w = 256, 256
square_size = 32
checkerboard = create_checkerboard(h, w, square_size)# 转换为 PyTorch 张量
checkerboard_tensor = torch.tensor(checkerboard, dtype=torch.float32).unsqueeze(0).unsqueeze(0)# 创建透视变换矩阵
perspective_matrix = torch.tensor([[1.0, 0.0, 0.0],[0.0, 1.0, 0.0],[0.0, 0.001, 1.0]
], dtype=torch.float32).unsqueeze(0)# 应用透视变换
transformed_checkerboard = perspective_transform(checkerboard_tensor, perspective_matrix)# 显示原始和变换后的图像
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.imshow(checkerboard, cmap='gray')
plt.title('Original Checkerboard')
plt.subplot(1, 2, 2)
plt.imshow(transformed_checkerboard[0, 0].detach().numpy(), cmap='gray')
plt.title('Transformed Checkerboard')
plt.show()# 测试梯度
perspective_matrix.requires_grad = True
transformed_checkerboard_grad = perspective_transform(checkerboard_tensor, perspective_matrix)
loss = transformed_checkerboard_grad.sum()
loss.backward()# 检查梯度是否存在
print("Perspective matrix gradient:", perspective_matrix.grad)
利用矩阵乘法解决这个问题。每次透视变换前,构造一个足够大的0值图像。对目标图像乘变换矩阵后,放入新建的图像中。注意不要让图像边缘超出去。
为了实现透视变换并确保梯度能够被正确计算,我们可以采取一种稍微不同的方法。这个方法包括以下步骤:
- 首先,我们会构建一个足够大的空白图像(全零值)作为变换后的画布。
- 然后,我们将使用透视变换矩阵来变换原始图像中的像素位置。
- 对于变换后的每个像素位置,我们将从原始图像中复制对应的像素值到新的位置上。
- 为了防止变换后的图像边缘超出新画布的边界,我们需要适当地选择画布的大小和变换矩阵。
这种方法可以通过矩阵乘法和索引操作来实现,允许在 PyTorch 中进行梯度的反向传播。我将编写一个示例实现来展示这个过程:
import torch
import numpy as np
import matplotlib.pyplot as pltdef apply_perspective_transform(image, perspective_matrix, output_size):n, c, h, w = image.shape# 创建输出图像(空白画布)output_image = torch.zeros(n, c, *output_size, device=image.device)# 生成网格y, x = torch.meshgrid(torch.linspace(-1, 1, h), torch.linspace(-1, 1, w))z = torch.ones_like(x)grid = torch.stack([x, y, z], dim=-1).view(-1, 3).t() # 3 x (H*W)# 应用透视变换transformed_grid = torch.mm(perspective_matrix, grid) # 3 x (H*W)# 将齐次坐标转换为笛卡尔坐标xy = transformed_grid[:2, :] / transformed_grid[2, :]xy = xy.t().view(h, w, 2)# 将变换后的坐标映射到输出图像上for i in range(h):for j in range(w):x, y = xy[i, j]if -1 <= x <= 1 and -1 <= y <= 1:# 将像素值复制到新位置xi, yi = int((x + 1) / 2 * (output_size[1] - 1)), int((y + 1) / 2 * (output_size[0] - 1))output_image[0, :, yi, xi] = image[0, :, i, j]return output_image
```



相关文章:
【pytorch】Pytorch 中的 grid 与 各种变换
Pytorch 中的 grid 与 各种变换 数学原理 **单应性(Homography) : 也就是透视变换。**单应性最初用来研究欧几里得几何中的透视和投影,而单应性一词,从词源学上来说,大致意思是“相似的绘图”。单应性的概念被引入来…...
【Linux】线程池实现
📗线程池实现(单例模式) 1️⃣线程池概念2️⃣线程池代码样例3️⃣部分问题与细节🔸类成员函数参数列表中隐含的this指针🔸单例模式🔸一个失误导致的bug 4️⃣调用线程池完成任务 1️⃣线程池概念 线程池是…...
使用Python批量上传本地maven库到nexus
背景:外包类项目开发时是调用的公司maven仓库进行开发,交付后需要将maven仓库转移到客户环境。 原理:1、打开idea运行源代码,将maven包下载到本地仓库, 2、下载包所在目录中执行脚本将本地仓库的maven包上传到客户nex…...
【Unity实战100例】Unity对Ini格式的配置文件管理和读写
目录 一.编写ini格式配置文件 二.读取解析ini文件 三.调用属性 INI 文件以文本形式存储,易于阅读和编辑。这种人可读的格式使得调整配置参数变得更加直观,不需要专门的工具。 INI 文件是一种轻量级的配置文件格式,不需要复杂的解析器或库。它的结构相对简单,适用于小到...
k8s存储卷和数据卷下
静态pv和pvc 运维负责pv:创建号持久化存储卷,申明好读写和挂载类型,以及可以提供的存储空间 Pvc开发做,要和开发沟通好,你期望的读写和挂载类型,以及存储空间 当我发布vc之后可以生成pv,还可以在…...
SQL Server 配置远程连接
Windows 安装好 SQL Server 的 SSMS,打开SSMS配置远程连接 找到 配置管理器 启用 TCP/IP 打开防火墙设置 新建入站规则 端口TCP - 特定本地端口 (1433)允许连接下一步名称完成 重启 SQL Server 服务...
vscode(visual studio code) 免密登陆服务器
1.生成密钥 首先,在本地,打开命令输入框: WinR–>弹出输入框,输入cmd,打开命令框。 然后,在命令框,输入 ssh-keygen -t rsa -C "love"按两次回车键,问你是否重写,选择…...
[redis] redis主从复制,哨兵模式和集群
一、redis的高可用 1.1 redis高可用的概念 在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。 高可用的计算公式是1-(宕机时间)/(宕机时…...
debian12部署Gitea服务
首先安装git、wget、sqlite,然后进行用户和组的相关设置 sudo apt install -y git wget sqlite3 新增一个git用户与一个git组 sudo adduser --system --group --disabled-password --shell /bin/bash --home /home/git --gecos Git Version Control git 给git用户设…...
js动态设置关键侦@keyframes
js动态设置关键侦keyframes 1.前置知识 关键侦keyframes规则通过在动画序列中定义关键侦的样式来控制CSS动画序列的中间步骤 keyframes slidein {from {transform: translateX(0%);}to {transform: translateX(100%);} } // from 等价于 0%;to 等价与 100% // 或…...
【WPF.NET开发】流文档
本文内容 什么是流文档?流文档类型创建流内容与流相关的类内容架构自定义文本 流文档旨在优化查看和可读性。 流文档根据运行时变量(例如,窗口大小、设备分辨率和可选的用户首选项)来动态调整和重新排列内容,而不是设…...
golang学习-结构体
1、定义 使用type 和struct 关键字来定义结构体,是值类型 格式如下: type 类型名 struct { 字段名 类型 字段名 类型 ... } 2、实例化 1、var 结构体实例 结构体类型 var p1 Person 2、使用new关键字 var p2 new(Person) 3、使用&对结构体…...
Python:enumerate() 函数
enumerate() 函数用于同时遍历索引和元素,常用于循环中。这个函数返回一个包含索引和元素的元组,可以通过解包的方式获取它们。 使用方法: enumerate(iterable, start0). iterable: 要遍历的可迭代对象。start: 索引起始值,默认…...
FPGA 移位运算与乘法
题目: 已知d为一个8位数,请在每个时钟周期分别输出该数乘1/3/7/8,并输出一个信号通知此时刻输入的d有效(d给出的信号的上升沿表示写入有效) 由题意可知: 复位信号高有效,低复位;在inpu_grant上升…...
网络安全B模块(笔记详解)- MYSQL信息收集
MYSQL信息收集 1.通过渗透机场景Kali中的渗透测试工具对服务器场景MySQL03进行服务信息扫描渗透测试(使用工具Nmap,使用必须要使用的参数),并将该操作显示结果中数据库版本信息作为Flag提交; Flag:MySQL 5.5.12 2.通过渗透机场景Kali中的渗透测试工具对服务器场景MySQL0…...
从JavaScript的角度上讲解一下xml
- XML(可扩展标记语言) XML(可扩展标记语言)是一种被设计用于存储和传输结构化数据的标记语言。它与HTML相似,但XML并没有预定义的标签,可以自定义标签及其属性。从JavaScript的角度来看,XML可以…...
Pandas实战100例 | 案例 13: 数据分类 - 使用 `cut` 对数值进行分箱
案例 13: 数据分类 - 使用 cut 对数值进行分箱 知识点讲解 在数据分析中,将连续的数值数据分类成不同的区间(或“分箱”)是一种常见的做法。Pandas 提供了 cut 函数,它可以根据你指定的分箱边界将数值数据分配到不同的类别中。 …...
python统计分析——操作案例(模拟抽样)
参考资料:用python动手学统计学 import numpy as np import pandas as pd from matplotlib import pyplot as plt import seaborn as snsdata_setpd.read_csv(r"C:\python统计学\3-4-1-fish_length_100000.csv")[length] #此处将文件路径改为自己的路…...
部署Tomcat及其负载均衡
Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。一般来说,Tomcat虽然和Apache或者Nginx这些Web服务器一样…...
C++ 类、结构体
C 类、结构体 类可以将变量、数组和函数完美地打包在一起。 类与结构体 类的定义: class Person {private:int age,height;double money;string books[100];public:string name;void say(){cout<<"Im"<<name<<endl;}int get_age(){…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
Python常用模块:time、os、shutil与flask初探
一、Flask初探 & PyCharm终端配置 目的: 快速搭建小型Web服务器以提供数据。 工具: 第三方Web框架 Flask (需 pip install flask 安装)。 安装 Flask: 建议: 使用 PyCharm 内置的 Terminal (模拟命令行) 进行安装,避免频繁切换。 PyCharm Terminal 配置建议: 打开 Py…...
相关类相关的可视化图像总结
目录 一、散点图 二、气泡图 三、相关图 四、热力图 五、二维密度图 六、多模态二维密度图 七、雷达图 八、桑基图 九、总结 一、散点图 特点 通过点的位置展示两个连续变量之间的关系,可直观判断线性相关、非线性相关或无相关关系,点的分布密…...
云原生安全实战:API网关Envoy的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关 作为微服务架构的统一入口,负责路由转发、安全控制、流量管理等核心功能。 2. Envoy 由Lyft开源的高性能云原生…...
