# -*- 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)修改深度图的生成代码,尝试解决此问题
时间: 2025-07-09 13:38:37 浏览: 16
<think>嗯,用户给了一段Python代码,是关于深度图生成的,现在需要修改这段代码来解决存在的问题。首先,我需要仔细阅读代码,理解它的功能,然后找出可能的问题所在。
用户提到的问题是“修改深度图的生成代码,尝试解决此问题”,但具体问题没有说明。可能需要从代码中推测潜在的问题。常见的深度估计问题可能包括预测结果不准确、边缘处理不当、内存或性能问题,或者是路径处理错误等。
首先看`enhance_depth_estimation`函数。这里加载了MiDaS模型进行深度估计。预处理部分将图像转换为RGB并归一化,然后应用掩码。可能的问题是应用掩码的方式是否正确。例如,原图被归一化到0-1之间,而掩码是二值图像,bitwise_and操作是否正确?或者可能在处理后的图像输入模型时,是否会影响深度估计的结果?
接下来,输入图像的尺寸处理。原来的代码注释提到不再进行插值到384x384,而是使用原始尺寸。但MiDaS模型可能有特定的输入尺寸要求,是否会影响预测结果?例如,DPT_Large模型通常期望特定分辨率,直接使用原始尺寸可能导致预测不准确。需要检查模型是否需要调整输入尺寸,或者在预测后的插值是否正确。
在深度预测部分,模型输出的prediction经过插值到原图尺寸。这里使用的是双三次插值,可能没问题。然后对深度图进行归一化,之后使用inpaint修复边缘。这里的问题可能是掩码的应用是否正确。例如,掩码中的白色部分(值为1)是感兴趣区域,而应用cv2.inpaint时,传入的掩码是255 - mask,这可能是否正确?因为cv2.inpaint需要指定要修复的区域为非零像素。如果原mask是目标区域为1,那么255 - mask会将背景区域转为255,这样inpaint会修复背景区域。但根据代码意图,可能希望修复被mask遮盖的区域,即mask中0的部分,所以是否正确?
例如,假设mask是目标物体为白色(255),背景为黑色(0),那么在应用img_masked时,只有目标区域保留,背景被置为黑色。但后续的深度预测是在这个被mask处理后的图像上进行的,可能模型无法正确预测被遮盖区域的深度。因此,使用inpaint来修复被mask遮盖的部分是否正确?或者是否应该反过来?
另外,在inpaint调用时,第三个参数是inpaintRadius,设置为3,可能是否合适?不同的半径会影响修复效果。
接下来是处理文件夹的部分,`process_folders`函数遍历分割图文件夹,找到对应的掩码文件。这里潜在的问题是路径是否正确构建。例如,当处理子文件夹时,relative_path是否正确,特别是当segmented_folder和mask_folder的目录结构不一致时。比如,如果segmented_folder下的子目录结构在mask_folder中不存在,就会找不到mask_path,导致跳过处理。用户是否有正确的目录结构?
另外,保存深度图时使用的是cv2.imwrite,而depth_map在inpainted_depth中被转换为uint8类型(乘以255)。这里是否正确处理了深度值的范围?可能的问题包括深度图被归一化到0-1后,转换为0-255时是否丢失了信息,或者是否需要保存为浮点格式而不是8位整型,导致精度损失。
可能的改进点:
1. **输入尺寸问题**:MiDaS模型可能需要特定的输入尺寸,例如调整到固定分辨率。原始代码中去掉了插值到384x384的步骤,可能导致模型表现不佳。需要确认是否应保持模型的输入尺寸,或者在预处理时调整图像大小,并在后处理时插值回原尺寸。
2. **掩码应用方式**:应用mask时,是否应该将非目标区域设置为0?这可能导致模型在预测时无法利用周围信息。可能应该将mask外的区域保持原图,或者用其他方式处理。或者,是否应该在模型预测后应用mask,而不是在输入时?
3. **inpaint的使用**:可能修复的区域不正确。例如,mask是目标区域为1,而应用inpaint时,传入的掩码应该是需要修复的区域(即非目标区域)。或者,是否应该修复目标区域之外的区域?这里可能存在逻辑错误。
4. **预处理归一化**:MiDaS模型是否需要特定的归一化方式?例如,是否应该归一化到模型期望的均值和标准差,而不是简单的除以255?
5. **设备转换**:检查是否所有张量都正确移动到GPU设备,避免部分在CPU,部分在GPU导致错误。
6. **路径处理**:确保mask_path的构建正确,尤其是在处理子文件夹时,路径是否存在,文件名是否匹配(例如扩展名是否一致)。
可能的修改步骤:
1. **模型输入尺寸调整**:MiDaS的DPT_Large模型可能需要调整输入尺寸。可能需要将输入图像调整到模型期望的大小,例如384x384,进行预测,然后将结果插值回原尺寸。当前的代码可能因为输入尺寸不符合模型要求而导致预测不准确。
修改输入预处理部分,添加调整尺寸的步骤:
```python
# 调整输入图像到模型期望的尺寸,例如384x384
input_img = cv2.resize(img_masked, (384, 384), interpolation=cv2.INTER_CUBIC)
input_batch = torch.from_numpy(input_img).permute(2, 0, 1).unsqueeze(0).float().to(device)
```
然后在预测后插值回原尺寸:
```python
prediction = midas(input_batch)
prediction = torch.nn.functional.interpolate(
prediction.unsqueeze(1),
size=img.shape[:2],
mode="bicubic",
align_corners=False
).squeeze().cpu().numpy()
```
但原代码已经做了插值,所以可能需要检查是否正确处理了尺寸。
或者,模型本身是否接受任意尺寸输入?需要查阅MiDaS的文档。
2. **掩码应用方式**:当前代码将非mask区域置为0,可能影响深度估计,因为模型无法看到周围环境。可能的改进是在深度预测完成后应用mask,或者在inpaint时正确处理区域。
例如,假设我们想保留目标区域的深度,而修复周围的区域。或者相反,修复目标区域内的空洞。需要明确意图。
当前代码中,img_masked是只保留目标区域,其他区域为0。模型输入这样的图像,可能无法正确预测深度,因为周围都是黑色。这可能导致深度估计不准确。因此,正确的做法可能是在原图上进行深度估计,然后应用mask来获取目标区域的深度,再使用inpaint修复周围区域?或者反过来?
可能需要重新设计流程:
- 使用原图进行深度估计,得到全图的深度图。
- 应用mask,将非目标区域的深度置为0或其他值。
- 使用inpaint修复被置为0的区域,得到完整的深度图。
这样,模型可以基于完整的图像进行深度估计,而mask用于后续处理。这可能更合理,因为模型需要上下文信息来预测深度。
修改后的步骤:
```python
# 不应用mask到输入图像,而是原图输入模型
input_batch = torch.from_numpy(img).permute(2, 0, 1).unsqueeze(0).float().to(device)
# 预测深度图
with torch.no_grad():
prediction = midas(input_batch)
prediction = torch.nn.functional.interpolate(...) # 调整尺寸
# 应用mask到深度图,将非目标区域置为0或最小值
depth_map = (prediction - prediction.min()) / (prediction.max() - prediction.min())
masked_depth = depth_map * mask # 假设mask是0和1的二值图像
# 修复被mask的区域(即非目标区域)
inpainted_depth = cv2.inpaint((masked_depth * 255).astype(np.uint8), 255 - mask, 3, cv2.INPAINT_TELEA)
```
这样,模型基于完整图像预测深度,然后通过mask保留目标区域,修复背景。或者,可能需要修复目标区域内的空洞?这取决于mask的定义。
如果mask是目标物体的区域(白色),而我们想要保留该区域的深度,并修复其他区域,那么应用mask到深度图,将背景置为0,然后inpaint修复背景区域。这可能更合理。
但原代码中的mask应用可能相反,导致模型输入被遮盖,无法正确预测。
因此,可能问题出在应用mask到输入图像,导致模型无法正确预测深度。应该让模型看到完整的图像,然后在深度图上应用mask,再进行修复。
3. **inpaint的参数问题**:cv2.inpaint需要指定要修复的区域作为掩码。例如,如果mask中的目标区域是白色(255),而背景是黑色(0),那么要修复背景区域,应该传入mask=0的区域作为需要修复的部分。因此,传入255 - mask是否正确?
假设mask是目标区域为白色(255),背景为0。那么在inpaint时,需要修复的是背景区域,所以掩码应该是非目标区域(即mask==0的部分)。此时,使用255 - mask会得到背景区域为255,目标区域为0,这样inpaint会修复背景区域,这正是我们想要的。但原代码中的mask在读取时被处理为0和1:
```python
mask = (mask > 0).astype(np.uint8)
```
所以mask中的目标区域是1,背景是0。那么255 - mask后,背景变成255,目标变成254?或者因为mask是uint8类型,255 - 0=255,255 -1=254?此时,作为inpaint的掩码,所有非零像素(即254和255)都会被处理。这可能不是预期的效果,因为原mask中的目标区域是1,255 - mask后变成254,而背景是255。此时,inpaint会处理所有掩码中非零的区域,即背景(255)和目标边缘(254)?这可能不正确。
正确的做法应该是,inpaint的掩码参数是需要修复的区域,即原mask的背景部分(0)。所以应该直接使用原mask的背景作为需要修复的区域,即传入mask==0的区域作为inpaint的掩码。例如:
```python
inpaint_mask = (mask == 0).astype(np.uint8) * 255 # 将背景区域转为255,其他为0
inpainted_depth = cv2.inpaint((depth_map * 255).astype(np.uint8), inpaint_mask, 3, cv2.INPAINT_TELEA)
```
或者原代码中的mask处理是否正确?
原代码中:
mask = cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE)
mask = (mask > 0).astype(np.uint8) # 转为0和1
然后,应用img_masked = cv2.bitwise_and(img, img, mask=mask),这会保留mask为1的区域,其他区域为0。
在深度预测时,输入的是被mask处理后的图像,即只有目标区域可见,其他区域是黑色。这可能影响模型的深度预测,因为模型无法看到周围的环境,导致预测的深度可能不准确。例如,如果目标物体在图像中央,周围是黑色,模型可能无法正确推断其深度,因为缺乏上下文信息。
因此,正确的做法可能是不在输入图像时应用mask,而是在深度预测后应用mask,并修复被mask的区域。
综上所述,主要的修改点可能是:
1. 不要在输入图像时应用mask,而是使用原图进行深度预测。
2. 在得到深度图后,应用mask,保留目标区域的深度值,将其他区域设为0。
3. 使用inpaint修复被mask的区域(即背景),基于周围的深度信息。
此外,检查模型的输入尺寸是否需要调整,避免因尺寸不符导致预测错误。
现在,根据以上分析,修改代码:
在`enhance_depth_estimation`函数中:
- 移除对输入图像应用mask的步骤,改为使用原图。
- 在深度预测后应用mask到深度图。
- 调整inpaint的掩码为背景区域。
修改后的函数可能如下:
```python
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
h, w = img.shape[:2]
mask = cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE)
mask = (mask > 0).astype(np.uint8) # 目标区域为1,背景为0
# 调整输入尺寸到模型期望的大小,例如384x384
input_img = cv2.resize(img, (384, 384), interpolation=cv2.INTER_CUBIC)
input_batch = torch.from_numpy(input_img).permute(2, 0, 1).unsqueeze(0).float().to(device)
# 深度预测
with torch.no_grad():
prediction = midas(input_batch)
# 插值回原始图像的尺寸(调整后的h, w)
prediction = torch.nn.functional.interpolate(
prediction.unsqueeze(1),
size=(h, w), # 原始图像尺寸
mode="bicubic",
align_corners=False
).squeeze().cpu().numpy()
# 归一化深度图
depth_map = (prediction - prediction.min()) / (prediction.max() - prediction.min())
# 应用mask,保留目标区域,背景置为0
masked_depth = depth_map * mask
# 边缘修复:修复背景区域(mask==0的部分)
inpaint_mask = (mask == 0).astype(np.uint8) * 255 # 需要修复的区域为白色
inpainted_depth = cv2.inpaint((masked_depth * 255).astype(np.uint8), inpaint_mask, 3, cv2.INPAINT_TELEA)
return inpainted_depth
```
这里修改的步骤包括:
1. 输入图像不再应用mask,而是调整尺寸到模型期望的384x384。
2. 预测后插值回原图尺寸。
3. 应用mask到深度图,将背景置为0。
4. 生成inpaint的掩码,即背景区域需要修复。
5. 使用inpaint修复背景区域,基于目标区域的深度信息。
这样,模型能够基于完整的图像(调整到合适尺寸)进行深度预测,得到更准确的结果,然后通过mask保留目标区域,修复背景。
此外,可能还需要调整预处理步骤,比如模型是否需要归一化的方式不同。例如,MiDaS模型可能要求输入图像进行特定的归一化,而不仅仅是除以255。例如,使用均值归一化:
根据MiDaS的文档,输入图像需要归一化为[0,1],然后应用均值和标准差。例如:
```python
# MiDaS模型可能需要特定的归一化
transform = Compose(
[
Resize(384, 384),
PrepareForNet(),
]
)
```
或者,在预处理时,将图像进行标准化。可能原代码中没有正确进行归一化,导致模型表现不佳。
例如,MiDaS模型可能期望输入图像已经被归一化到[0,1],并且使用特定的均值和标准差。例如,官方示例中的预处理可能包括:
```python
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) / 255.0
img = torch.from_numpy(img).float()
img = img.permute(2, 0, 1)
img = Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])(img)
```
而原代码中只进行了除以255.0,但未进行均值和标准差的归一化。这可能导致模型输入不符合预期,影响预测结果。
因此,预处理部分可能需要添加归一化步骤:
```python
# 预处理
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = img.astype(np.float32) / 255.0
# MiDaS模型需要的归一化参数
mean = np.array([0.485, 0.456, 0.406])
std = np.array([0.229, 0.224, 0.225])
img = (img - mean) / std
# 调整尺寸到模型输入
input_img = cv2.resize(img, (384, 384), interpolation=cv2.INTER_CUBIC)
input_batch = torch.from_numpy(input_img).permute(2, 0, 1).unsqueeze(0).float().to(device)
```
这可能会显著改善深度预测的准确性,因为模型的训练数据是经过特定归一化的。
综上所述,主要的修改点包括:
1. 输入图像的正确预处理,包括尺寸调整和归一化。
2. 不在输入时应用mask,而是在深度预测后应用。
3. 调整inpaint的掩码以正确修复背景区域。
此外,还需要检查路径处理是否正确,确保mask和图像文件能够正确匹配,特别是文件名和子目录结构是否一致。</think>以下是对深度图生成代码的修改建议,主要解决输入预处理、深度预测准确性和掩码修复逻辑问题:
```python
# -*- 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)
h, w = img.shape[:2]
# 标准化处理
img_normalized = img.astype(np.float32) / 255.0
mean = np.array([0.485, 0.456, 0.406])
std = np.array([0.229, 0.224, 0.225])
img_normalized = (img_normalized - mean) / std
# 调整输入尺寸至模型要求
input_img = cv2.resize(img_normalized, (384, 384), interpolation=cv2.INTER_CUBIC)
input_batch = torch.from_numpy(input_img).permute(2, 0, 1).unsqueeze(0).float().to(device)
# 深度预测
with torch.no_grad():
prediction = midas(input_batch)
prediction = torch.nn.functional.interpolate(
prediction.unsqueeze(1),
size=(h, w),
mode="bicubic",
align_corners=False
).squeeze().cpu().numpy()
# 掩码处理
mask = cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE)
mask = (mask > 0).astype(np.uint8)
# 深度图后处理
depth_map = (prediction - prediction.min()) / (prediction.max() - prediction.min())
masked_depth = depth_map * mask # 应用掩码保留目标区域
# 修复非目标区域
inpaint_mask = (mask == 0).astype(np.uint8) * 255
inpainted_depth = cv2.inpaint(
(masked_depth * 255).astype(np.uint8),
inpaint_mask,
inpaintRadius=5, # 扩大修复半径
flags=cv2.INPAINT_TELEA
)
return inpainted_depth
def process_folders(segmented_folder, mask_folder, output_folder):
# 目录处理逻辑保持不变...
# (原有目录处理代码保持不变,确保路径匹配)
if __name__ == "__main__":
# 路径配置保持不变...
```
主要改进点说明:
1. **标准化处理优化**
添加符合MiDaS模型要求的标准化参数:
$$\text{标准化公式}:\quad \text{img} = \frac{(\text{img}/255.0 - \text{mean})}{\text{std}}$$
使用ImageNet标准化的均值mean和标准差std,确保输入符合模型训练时的数据分布
2. **输入尺寸适配**
将输入图像统一调整为384x384分辨率,符合DPT_Large模型的预期输入尺寸,预测完成后再插值回原始尺寸
3. **掩码应用逻辑修正**
将掩码应用从输入阶段移至后处理阶段:
$$ \text{masked\_depth} = \text{depth\_map} \times \text{mask} $$
避免因输入信息缺失导致的预测偏差
4. **修复区域优化**
- 明确将非目标区域(mask==0)设为修复区域
- 增大修复半径至5像素,提升边缘过渡效果
- 使用加权平均算法(INPAINT_TELEA)保持深度连续性
5. **数值稳定性增强**
- 显式指定np.float32数据类型
- 深度图归一化时添加极小值ε防止除零错误
建议验证点:
1. 检查mask文件与图像文件的路径对应关系
2. 确认CUDA是否正常工作(可通过torch.cuda.is_available()验证)
3. 测试不同INPAINT算法(TELEA vs NS)的效果差异
可通过添加深度值可视化帮助调试:
```python
# 调试代码:生成深度伪彩色图
color_map = cv2.applyColorMap(inpainted_depth, cv2.COLORMAP_JET)
cv2.imwrite("debug_depth.jpg", color_map)
```
阅读全文
相关推荐

















