如何进行 interpolate_depth , 如何对深度进行插值

本文解析了D2net中interpolate_depth函数,通过实例说明如何从高分辨率深度图中为低分辨率特征图插值深度值,解释了坐标筛选、深度检查和返回结果的重要性。涉及的关键概念包括坐标合法性、下采样深度匹配和索引操作。

如果乍一看,比较奇怪的就是 D2net的 interpolate_depth的代码了,这里就进行我的粗浅的理解分析。

首先是这部分代码:
在这里插入图片描述
如果我用一句话概括,就这这里进行了简单的坐标是否合法的筛选, 因为按照前面教程,咱们输入的 pos 是一个小数的坐标。 这里得到的 valid_corners 其实就是 判断 例如 (3.5 7.5 )这个坐标的左上,左下,右上,右下是不是合法的坐标。 3.5 7.5 的四个角那肯定是没问题的啊。 但是你说 0,0 这个位置,他的左上角就是不存在的,所以说需要筛选一下,就是这回事。
这里得到的 valid_corners 就是一个 True False 的Mask。 指示每个坐标是不是合法的。


紧接着呢, 是把所有合法的四个角,分成四份 取出来。 如下所示。
然后直接index 在深度图上,看看深度图的这些角处,是不是合法的深度。从而再次生成一个 depth_mask。 代表depth中每个点是不是合法的。
在这里插入图片描述
直接看最终的结果,你只用记住下面的东西:
假如输入的 pos 是60 x 80 的, 而 最原始的depth是 480x640 的。
理论上来说,很难得到 下采样 1/8 的特征图,每个点的真实深度值对吧。因为这里的特征图,是60x80的根本和原始的深度值 480x640对不上号啊对吧。 但是,我们就是要通过 480x640的深度图插值出, 特征图每个点对应的4800个深度!!!注意这4800个点,可不是每个点都有深度的,可能有深度的只有 4700个点
知道了上面的东西后, 接着看代码的三个返回结果。 分别是:

# -*- coding: gbk -*- import cv2 import torch import numpy as np import os def enhance_depth_estimation(img_path, mask_path): # 加载模型 midas = torch.hub.load("/home/lichuang/project/Opencv-main/sam_yolo/MiDaS/", "DPT_Large", source='local') device = torch.device("cuda" if torch.cuda.is_available() else "cpu") midas.to(device) midas.eval() # 预处理 img = cv2.imread(img_path) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) / 255.0 mask = cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE) # 确保 mask 中的值为 0 和 1,白色部分为 1 mask = (mask > 0).astype(np.uint8) # 应用 mask img_masked = cv2.bitwise_and(img, img, mask=mask) # 转换为模型输入格式,使用图像原始尺寸 input_batch = torch.from_numpy(img_masked).permute(2, 0, 1).unsqueeze(0).float().to(device) # 不再进行插值到 (384, 384) # 深度预测 with torch.no_grad(): prediction = midas(input_batch) prediction = torch.nn.functional.interpolate( prediction.unsqueeze(1), size=img.shape[:2], # 使用图像原始尺寸 mode="bicubic", align_corners=False ).squeeze().cpu().numpy() # 边缘修复 depth_map = (prediction - prediction.min()) / (prediction.max() - prediction.min()) inpainted_depth = cv2.inpaint((depth_map * 255).astype(np.uint8), 255 - mask, 3, cv2.INPAINT_TELEA) return inpainted_depth def process_folders(segmented_folder, mask_folder, output_folder): # 确保输出文件夹存在 os.makedirs(output_folder, exist_ok=True) # 递归遍历分割图文件夹 for root, _, files in os.walk(segmented_folder): for filename in files: if filename.endswith(('.png', '.jpg', '.jpeg')): img_path = os.path.join(root, filename) # 计算相对路径 relative_path = os.path.relpath(root, segmented_folder) mask_path = os.path.join(mask_folder, relative_path, filename) # 检查对应的掩码文件是否存在 if not os.path.exists(mask_path): print(f"未找到对应的掩码文件: {mask_path},跳过 {img_path}。") continue # 生成深度图 depth_map = enhance_depth_estimation(img_path, mask_path) # 构建输出路径,保持子文件夹结构 output_subfolder = os.path.join(output_folder, relative_path) os.makedirs(output_subfolder, exist_ok=True) output_path = os.path.join(output_subfolder, filename) # 保存深度图 cv2.imwrite(output_path, depth_map) print(f"已为 {img_path} 生成深度图并保存到 {output_path}。") if __name__ == "__main__": segmented_folder = "/home/lichuang/project/Opencv-main/sam_yolo/dataset/input_images/" # 替换为实际的分割图文件夹路径 mask_folder = "/home/lichuang/project/Opencv-main/sam_yolo/dataset/masks/" # 替换为实际的掩码文件夹路径 output_folder = "/home/lichuang/project/Opencv-main/sam_yolo/dataset/depth_maps1/" # 替换为实际的输出深度图文件夹路径 process_folders(segmented_folder, mask_folder, output_folder)修改深度图的生成代码,尝试解决此问题
03-21
### 使用 `grid_sample` 实现特征图的 warp 操作 在深度学习中,`grid_sample` 是一个常用函数,用于对特征图进行非规则采样,从而实现 warp 操作。其核心思想是根据一个采样网格(grid)将输入特征图映射到新的位置,实现图像或特征图的几何变换。与 `interpolate` 不同的是,`grid_sample` 支持非均匀采样,可以实现更灵活的变形操作[^1]。 `grid_sample` 的底层实现基于双线性插值,能够自动处理浮点坐标的采样,并在训练过程中支持梯度反向传播。因此,它广泛应用于光流估计、图像变形、数据增强等任务中。 #### 使用方法 在 PyTorch 中,`grid_sample` 的调用方式如下: ```python torch.nn.functional.grid_sample(input, grid, mode='bilinear', padding_mode='zeros', align_corners=True) ``` 其中: - `input` 是输入的特征图(形状为 `[N, C, H, W]`)。 - `grid` 是一个采样点的坐标网格(形状为 `[N, H, W, 2]`),每个点包含 `(x, y)` 坐标,范围在 `[-1, 1]` 之间。 - `mode` 指定插值方式,可选 `'nearest'` 或 `'bilinear'`。 - `padding_mode` 指定边界外推策略,可选 `'zeros'`、`'border'` 或 `'reflection'`。 - `align_corners` 控制坐标映射方式,影响插值结果的对齐方式。 #### 构建采样网格 在实际应用中,`grid` 通常由仿射变换矩阵或光流场生成。例如,在光流估计任务中,`grid` 可以通过将光流向量加到原始网格上获得: ```python import torch import torch.nn.functional as F # 假设输入图像尺寸为 (B, C, H, W) def backwarp(tenInput, tenFlow): N, _, H, W = tenInput.shape # 生成基础网格 grid_y, grid_x = torch.meshgrid(torch.linspace(-1, 1, H), torch.linspace(-1, 1, W)) grid = torch.stack([grid_x, grid_y], dim=0).unsqueeze(0).repeat(N, 1, 1, 1).to(tenInput.device) # 添加光流向量 tenFlow = torch.cat([ tenFlow[:, 0:1, :, :] / ((W - 1.0) / 2.0), tenFlow[:, 1:2, :, :] / ((H - 1.0) / 2.0) ], dim=1) grid = (grid + tenFlow).permute(0, 2, 3, 1) return F.grid_sample(tenInput, grid, mode='bilinear', padding_mode='border', align_corners=True) ``` 上述代码中,首先生成一个覆盖整个图像范围的网格,然后根据光流向量对其进行偏移,最终通过 `grid_sample` 实现 warp 操作[^3]。 #### 生成随机形变场 在数据增强或生成模型中,可以通过随机形变场实现非规则变形。例如,生成 3D 随机噪声形变场的方法如下: ```python import numpy as np def create_random_noise_deformation_field_3d(depth, height, width, scale=1): grid_z, grid_y, grid_x = np.mgrid[0:depth, 0:height, 0:width] noise_x = np.random.uniform(-scale, scale, (depth, height, width)) noise_y = np.random.uniform(-scale, scale, (depth, height, width)) noise_z = np.random.uniform(-scale, scale, (depth, height, width)) warp_field_x = (grid_x + noise_x) / width * 2 - 1 warp_field_y = (grid_y + noise_y) / height * 2 - 1 warp_field_z = (grid_z + noise_z) / depth * 2 - 1 return np.stack((warp_field_x, warp_field_y, warp_field_z), axis=-1) ``` 该方法生成的形变场可用于 `grid_sample`,实现对 3D 特征图的随机变形[^2]。 #### 应用场景 - **光流估计**:利用 `grid_sample` 对后一帧图像进行 warp 操作,使其与前一帧图像对齐,用于计算光流损失。 - **图像变形**:结合仿射变换矩阵或随机形变场,实现图像的非刚性变形。 - **数据增强**:通过随机形变增强训练数据的多样性,提高模型泛化能力。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值