| import sys |
| sys.path.append('Depth-Anything-V2') |
|
|
| import cv2 |
| import torch |
| import matplotlib.pyplot as plt |
| import numpy as np |
| from PIL import Image |
| from depth_anything_v2.dpt import DepthAnythingV2 |
| from pathlib import Path |
| from tqdm.auto import tqdm |
| import argparse |
|
|
|
|
| def parse_args(): |
| parser = argparse.ArgumentParser(description='Generate depth and normal maps from images') |
| parser.add_argument('--source_root', type=str, default='test_dir', |
| help='Root directory containing the images') |
| parser.add_argument('--model_path', type=str, |
| default='depth_anything_v2_vitl.pth', |
| help='Path to the depth model checkpoint') |
| return parser.parse_args() |
|
|
|
|
| def generate_depth_maps(source_root, model_path): |
| source_root = Path(source_root) |
| origin = source_root / 'origin' |
| to_depth_list = [origin] |
|
|
| model = DepthAnythingV2(encoder='vitl', features=256, out_channels=[256, 512, 1024, 1024]).cuda() |
| model.load_state_dict(torch.load(model_path, map_location='cpu')) |
| model.eval() |
|
|
| depth_path = source_root / 'depth' |
| depth_path.mkdir(parents=True, exist_ok=True) |
|
|
| with torch.inference_mode(): |
| for to_depth_item in to_depth_list: |
| folder_name = to_depth_item.stem |
| dst_path = depth_path |
|
|
| dst_path.mkdir(parents=True, exist_ok=True) |
| |
| bar = tqdm(to_depth_item.glob('*')) |
|
|
| for image_path in bar: |
| try: |
| raw_img = cv2.imread(str(image_path)) |
| depth = model.infer_image(raw_img) |
|
|
| depth = (depth - depth.min()) / (depth.max() - depth.min()) * 255.0 |
| depth = depth.astype(np.uint8) |
|
|
| np.save(f'{dst_path}/{image_path.stem}.npy', depth) |
|
|
| except Exception as e: |
| print(e) |
| continue |
| |
| return depth_path |
|
|
|
|
| def calculate_normal_map(img_path: Path, ksize=5): |
| |
| depth = np.load(img_path).astype(np.float32) |
|
|
| |
| dx = cv2.Sobel(depth, cv2.CV_32F, 1, 0, ksize=ksize) |
| dy = cv2.Sobel(depth, cv2.CV_32F, 0, 1, ksize=ksize) |
|
|
| |
| dz = np.ones_like(dx) * -1 |
|
|
| |
| normals = np.stack((dx, dy, dz), axis=-1) |
|
|
| |
| norm = np.linalg.norm(normals, axis=-1, keepdims=True) |
| normals /= (norm + 1e-6) |
|
|
| |
| normal_map = (normals + 1) / 2 * 255 |
| normal_map = normal_map.astype("uint8") |
|
|
| normal_map = normal_map.transpose(2, 0, 1) |
|
|
| return normal_map |
|
|
|
|
| def generate_normal_maps(source_root, ksize=5): |
| source_root = Path(source_root) |
| depth_root = source_root / 'depth' |
| normal_root = source_root / 'normal' |
| normal_root.mkdir(parents=True, exist_ok=True) |
|
|
| bar = tqdm(list(depth_root.glob('*.npy'))) |
|
|
| for depth_img_path in bar: |
| img_name = depth_img_path.name |
|
|
| normal_map = calculate_normal_map(depth_img_path, ksize=ksize) |
|
|
| np.save(f'{normal_root}/{img_name}', normal_map) |
|
|
|
|
| def main(): |
| args = parse_args() |
| |
| print(f"Generating depth maps from images in {args.source_root}") |
| depth_path = generate_depth_maps(args.source_root, args.model_path) |
| |
| print(f"Generating normal maps from depth maps") |
| generate_normal_maps(args.source_root) |
| |
| print("Processing complete!") |
|
|
|
|
| if __name__ == "__main__": |
| main() |