当前位置: 首页 > news >正文

【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_gridgrid_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] 进行填充。
  • startpointsendpoints 分别指定了原始四边形和目标四边形的四个顶点,通过这些顶点之间的映射关系,函数将原始图像进行透视变换。 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值图像。对目标图像乘变换矩阵后,放入新建的图像中。注意不要让图像边缘超出去。

为了实现透视变换并确保梯度能够被正确计算,我们可以采取一种稍微不同的方法。这个方法包括以下步骤:

  1. 首先,我们会构建一个足够大的空白图像(全零值)作为变换后的画布。
  2. 然后,我们将使用透视变换矩阵来变换原始图像中的像素位置。
  3. 对于变换后的每个像素位置,我们将从原始图像中复制对应的像素值到新的位置上。
  4. 为了防止变换后的图像边缘超出新画布的边界,我们需要适当地选择画布的大小和变换矩阵。

这种方法可以通过矩阵乘法和索引操作来实现,允许在 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
```![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a0b5ce4a275d4d68a95c885a513af1af.png#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/811d7261f2cc4b2d835bff3553258b59.png#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/d52d11559e61484c98f7d4e1c502e16e.png#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/30dc001dbb0649b3a2e0e546c9e07a63.png#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/154dcdacf669468e8919ef0dffe6620e.png#pic_center)

相关文章:

【pytorch】Pytorch 中的 grid 与 各种变换

Pytorch 中的 grid 与 各种变换 数学原理 **单应性&#xff08;Homography&#xff09; : 也就是透视变换。**单应性最初用来研究欧几里得几何中的透视和投影&#xff0c;而单应性一词&#xff0c;从词源学上来说&#xff0c;大致意思是“相似的绘图”。单应性的概念被引入来…...

【Linux】线程池实现

&#x1f4d7;线程池实现&#xff08;单例模式&#xff09; 1️⃣线程池概念2️⃣线程池代码样例3️⃣部分问题与细节&#x1f538;类成员函数参数列表中隐含的this指针&#x1f538;单例模式&#x1f538;一个失误导致的bug 4️⃣调用线程池完成任务 1️⃣线程池概念 线程池是…...

使用Python批量上传本地maven库到nexus

背景&#xff1a;外包类项目开发时是调用的公司maven仓库进行开发&#xff0c;交付后需要将maven仓库转移到客户环境。 原理&#xff1a;1、打开idea运行源代码&#xff0c;将maven包下载到本地仓库&#xff0c; 2、下载包所在目录中执行脚本将本地仓库的maven包上传到客户nex…...

【Unity实战100例】Unity对Ini格式的配置文件管理和读写

目录 一.编写ini格式配置文件 二.读取解析ini文件 三.调用属性 INI 文件以文本形式存储,易于阅读和编辑。这种人可读的格式使得调整配置参数变得更加直观,不需要专门的工具。 INI 文件是一种轻量级的配置文件格式,不需要复杂的解析器或库。它的结构相对简单,适用于小到...

k8s存储卷和数据卷下

静态pv和pvc 运维负责pv&#xff1a;创建号持久化存储卷&#xff0c;申明好读写和挂载类型&#xff0c;以及可以提供的存储空间 Pvc开发做&#xff0c;要和开发沟通好&#xff0c;你期望的读写和挂载类型&#xff0c;以及存储空间 当我发布vc之后可以生成pv&#xff0c;还可以在…...

SQL Server 配置远程连接

Windows 安装好 SQL Server 的 SSMS,打开SSMS配置远程连接 找到 配置管理器 启用 TCP/IP 打开防火墙设置 新建入站规则 端口TCP - 特定本地端口 (1433)允许连接下一步名称完成 重启 SQL Server 服务...

vscode(visual studio code) 免密登陆服务器

1.生成密钥 首先&#xff0c;在本地&#xff0c;打开命令输入框&#xff1a; WinR–>弹出输入框&#xff0c;输入cmd,打开命令框。 然后&#xff0c;在命令框&#xff0c;输入 ssh-keygen -t rsa -C "love"按两次回车键&#xff0c;问你是否重写&#xff0c;选择…...

[redis] redis主从复制,哨兵模式和集群

一、redis的高可用 1.1 redis高可用的概念 在web服务器中&#xff0c;高可用是指服务器可以正常访问的时间&#xff0c;衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。 高可用的计算公式是1-&#xff08;宕机时间&#xff09;/&#xff08;宕机时…...

debian12部署Gitea服务

首先安装git、wget、sqlite&#xff0c;然后进行用户和组的相关设置 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%&#xff1b;to 等价与 100% // 或…...

【WPF.NET开发】流文档

本文内容 什么是流文档&#xff1f;流文档类型创建流内容与流相关的类内容架构自定义文本 流文档旨在优化查看和可读性。 流文档根据运行时变量&#xff08;例如&#xff0c;窗口大小、设备分辨率和可选的用户首选项&#xff09;来动态调整和重新排列内容&#xff0c;而不是设…...

golang学习-结构体

1、定义 使用type 和struct 关键字来定义结构体&#xff0c;是值类型 格式如下&#xff1a; type 类型名 struct { 字段名 类型 字段名 类型 ... } 2、实例化 1、var 结构体实例 结构体类型 var p1 Person 2、使用new关键字 var p2 new(Person) 3、使用&对结构体…...

Python:enumerate() 函数

enumerate() 函数用于同时遍历索引和元素&#xff0c;常用于循环中。这个函数返回一个包含索引和元素的元组&#xff0c;可以通过解包的方式获取它们。 使用方法&#xff1a; enumerate(iterable, start0). iterable: 要遍历的可迭代对象。start: 索引起始值&#xff0c;默认…...

FPGA 移位运算与乘法

题目&#xff1a; 已知d为一个8位数&#xff0c;请在每个时钟周期分别输出该数乘1/3/7/8,并输出一个信号通知此时刻输入的d有效&#xff08;d给出的信号的上升沿表示写入有效&#xff09; 由题意可知&#xff1a; 复位信号高有效&#xff0c;低复位&#xff1b;在inpu_grant上升…...

网络安全B模块(笔记详解)- MYSQL信息收集

MYSQL信息收集 1.通过渗透机场景Kali中的渗透测试工具对服务器场景MySQL03进行服务信息扫描渗透测试(使用工具Nmap,使用必须要使用的参数),并将该操作显示结果中数据库版本信息作为Flag提交; Flag:MySQL 5.5.12 2.通过渗透机场景Kali中的渗透测试工具对服务器场景MySQL0…...

从JavaScript的角度上讲解一下xml

- XML&#xff08;可扩展标记语言&#xff09; XML&#xff08;可扩展标记语言&#xff09;是一种被设计用于存储和传输结构化数据的标记语言。它与HTML相似&#xff0c;但XML并没有预定义的标签&#xff0c;可以自定义标签及其属性。从JavaScript的角度来看&#xff0c;XML可以…...

Pandas实战100例 | 案例 13: 数据分类 - 使用 `cut` 对数值进行分箱

案例 13: 数据分类 - 使用 cut 对数值进行分箱 知识点讲解 在数据分析中&#xff0c;将连续的数值数据分类成不同的区间&#xff08;或“分箱”&#xff09;是一种常见的做法。Pandas 提供了 cut 函数&#xff0c;它可以根据你指定的分箱边界将数值数据分配到不同的类别中。 …...

python统计分析——操作案例(模拟抽样)

参考资料&#xff1a;用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应用服务器&#xff0c;属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发和调试JSP程序的首选。一般来说&#xff0c;Tomcat虽然和Apache或者Nginx这些Web服务器一样&#xf…...

C++ 类、结构体

C 类、结构体 类可以将变量、数组和函数完美地打包在一起。 类与结构体 类的定义&#xff1a; class Person {private:int age,height;double money;string books[100];public:string name;void say(){cout<<"Im"<<name<<endl;}int get_age(){…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

Linux 中如何提取压缩文件 ?

Linux 是一种流行的开源操作系统&#xff0c;它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间&#xff0c;使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的&#xff0c;要在 …...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...